Dictionary into dictionary in python - python

Ok, this one should be simple. I have 3 dictionaries. They are all made, ordered, and filled to my satisfaction but I would like to put them all in an overarching dictionary so I can reference and manipulate them more easily and efficiently.
Layer0 = {}
Layer1 = {}
Layer2 = {}
here they are when created, and afterwards I feebly tried different things based on SO questions:
Layers = {Layer0, Layer1, Layer2}
which raised a syntax error
Layers = {'Layer0', 'Layer1', 'Layer2'}
which raised another syntax error
(Layers is the Dictionary I'm trying to create that will have all the previously made dictionaries within it)
All the other examples I found on SO have been related to creating dictionaries within dictionaries in order to fill them (or filling them simultaneously) and since I already coded a large number of lines to make these dictionaries, I'd rather put them into a dictionary after the fact instead of re-writing code.
It would be best if the order of the dictionaries are preserved when put into Layers
Does anyone know if this is possible and how I should do it?

Dictionary items have both a key and a value.
Layers = {'Layer0': Layer0, 'Layer1': Layer1, 'Layer2': Layer2}

Keep in mind that dictionaries don't have an order, since a dictionary is a hash table (i.e. a mapping from your key names to a unique hash value). Using .keys() or .values() generates a list, which does have an order, but the dictionary itself doesn't.
So when you say "It would be best if the order of the dictionaries are preserved when put into Layers" - this doesn't really mean anything. For example, if you rename your dictionaries from "Layer1, Layer2, Layer3" to "A, B, C," you'll see that Layers.keys() prints in the order "A, C, B." This is true regardless of the order you used when building the dictionary. All this shows is that the hash value of "C" is less than that of "B," and it doesn't tell you anything about the structure of your dictionary.
This is also why you can't directly iterate over a dictionary (you have to iterate over e.g. a list of the keys).
As a side note, this hash function is what allows a dictionary to do crazy fast lookups. A good hash function will give you constant time [O(1)] lookup, meaning you can check if a given item is in your dictionary in the same amount of time whether the dictionary contains ten items or ten million. Pretty cool.

Related

Unpacking a list of dictionaries to get all their keys

I am writing a script to add missing keys within a list of dictionaries and assign them a default value. I start by building a set of all the possible keys that appear in one or more dictionaries.
I adapted a nice snippet of code for this but I'm having trouble fully wrapping my head around how it works:
all_keys = set().union(*dicts)
From how I understand this, my list of dictionaries dicts is unpacked into individual (dictionary) arguments for the union method, which merges them all together with the empty set, giving me a set of keys.
What isn't clear to me is why this code builds the set using just the keys of the dictionaries, while discarding their associated values. This is in fact what I want to happen, but how it is achieved here is murky. For example, I know unpacking a dictionary with a single * unpacks just the keys, which seems like what is happening here, except in my code I am not explicitly unpacking the contents of the dictionaries, only the list that contains them.
Can someone explain to me a little more explicitly what is happening under the hood here?
If you wrote:
s1 = set()
s2 = s1.union(iterable1, iterable2, iterable3)
the union() method would unpack each iterableX to get the values to combine with s1.
Your code is simply getting all the iterables by spreading dicts, so it's equivalent to
s2 = s1.union(dicts[0], dicts[1], dicts[2], ...)
and it unpacks each dictionary, getting their keys.

why use a dictionary if a List combined with Tuples offers way more flexibility?

new to Python, trying to learn how to use dictionaries, but honestly don't see the point, you're limited to 2 pairs whereas if I just make a list with Tuples I get far more flexibility
in the code below I made a list of superheroes, where u can look it up by
Name(Batman), Identity (Bruce Wayne) or Universe (DC)
can't do that on a dictionary (you're limited to pairs of 2) so why would I ever need a dictionary?
Superheroes = [('Batman','Bruce Wayne','DC'),('Spiderman','Peter Parker','Marvel'),('Superman','Clark Kent','DC'),('Ironman','Tony Stark','Marvel'),('Green Arrow','Oliver Queen','DC')]
user_selection = input()
for (name,identity,universe) in Superheroes:
if name==user_selection or identity == user_selection or universe == user_selection:
print('Hero:' + name + '\nSecret Identity:' + identity + '\nUniverse:'+ universe)
else:
continue
Most uses of dictionaries don't require searching for a match in both the keys and values. You design your data structure so that the item you normally need to look up is the dictionary key.
For instance, if you have data with ingredients in recipes, you would almost always be looking it up by the dish that you're cooking. So you make that the key and you can get all the ingredients with a single lookup instead of searching the entire list.
If you occasionally need to find something in the value, you can still iterate through the dictionary using dict.entries(). If you need to look up by different components frequently you can make multiple dictionaries that all refer to the same values using different keys.

Why does a set display in same order if sets are unordered?

I'm taking a first look at the python language from Python wikibook.
For sets the following is mentioned:
We can also have a loop move over each of the items in a set. However, since sets are unordered, it is undefined which order the iteration will follow.
and the code example given is :
s = set("blerg")
for letter in s:
print letter
Output:
r b e l g
When I run the program I get the results in the same order, no matter how many times I run. If sets are unordered and order of iteration is undefined, why is it returning the set in the same order? And what is the basis of the order?
They are not randomly ordered, they are arbitrarily ordered. It means you should not count on the order of insertions being maintained as the actual internal implementation details determine the order instead.
The order depends on the insertion and deletion history of the set.
In CPython, sets use a hash table, where inserted values are slotted into a sparse table based on the value returned from the hash() function, modulo the table size and a collision handling algorithm. Listing the set contents then returns the values as ordered in this table.
If you want to go into the nitty-gritty technical details then look at Why is the order in dictionaries and sets arbitrary?; sets are, at their core, dictionaries where the keys are the set values and there are no associated dictionary values. The actual implementation is a little more complicated, as always, but that answer will suffice to get you most of the way there. Then look at the C source code for set for the rest of those details.
Compare this to lists, which do have a fixed order that you can influence; you can move items around in the list and the new ordering would be maintained for you.

Look up python dict value by expression

I have a dict that has unix epoch timestamps for keys, like so:
lookup_dict = {
1357899: {} #some dict of data
1357910: {} #some other dict of data
}
Except, you know, millions and millions and millions of entries. I'd like to subset this dict, over and over again. Ideally, I'd love to be able to write something like I can in R, like:
lookup_value = 1357900
dict_subset = lookup_dict[key >= lookup_value]
# dict_subset now contains {1357910: {}}
But I confess, I can't find any actual proof that this is something Python can do without having, one way or the other, to iterate over every row. If I understand Python correctly (and I might not), key lookup of the form key in dict uses binary search, and is thus very fast; any way to do a binary search, on dict keys?
To do this without iterating, you're going to need the keys in sorted order. Then you just need to do a binary search for the first one >= lookup_value, instead of checking each one for >= lookup_value.
If you're willing to use a third-party library, there are plenty out there. The first two that spring to mind are bintrees (which uses a red-black tree, like C++, Java, etc.) and blist (which uses a B+Tree). For example, with bintrees, it's as simple as this:
dict_subset = lookup_dict[lookup_value:]
And this will be as efficient as you'd hope—basically, it adds a single O(log N) search on top of whatever the cost of using that subset. (Of course usually what you want to do with that subset is iterate the whole thing, which ends up being O(N) anyway… but maybe you're doing something different, or maybe the subset is only 10 keys out of 1000000.)
Of course there is a tradeoff. Random access to a tree-based mapping is O(log N) instead of "usually O(1)". Also, your keys obviously need to be fully ordered, instead of hashable (and that's a lot harder to detect automatically and raise nice error messages on).
If you want to build this yourself, you can. You don't even necessarily need a tree; just a sorted list of keys alongside a dict. You can maintain the list with the bisect module in the stdlib, as JonClements suggested. You may want to wrap up bisect to make a sorted list object—or, better, get one of the recipes on ActiveState or PyPI to do it for you. You can then wrap the sorted list and the dict together into a single object, so you don't accidentally update one without updating the other. And then you can extend the interface to be as nice as bintrees, if you want.
Using the following code will work out
some_time_to_filter_for = # blah unix time
# Create a new sub-dictionary
sub_dict = {key: val for key, val in lookup_dict.items()
if key >= some_time_to_filter_for}
Basically we just iterate through all the keys in your dictionary and given a time to filter out for we take all the keys that are greater than or equal to that value and place them into our new dictionary

Insert Variable Dictionary Values to db

I have a dictionary whose keys and values are updated from internet. This dictionary keeps changing the position and number of its keys/variables on every update (for some reason) but the names of keys and formats of values remain the same. Initially, I converted its keys and values to different arrays and was storing their values to database by following their array locaton, but after I discovered its variability, its no more possible to do it the same way I was doing, since the len(dictionary) keeps changing. The dictionary items are fetched from a url on every update, which sometime gives me 31 items (each item is key:value) and sometime gives me 3, 29 , 28 or even 27 items in the dictionary. So, I have made a generalization about some 'always-there' items and now I want to extract them on every update, but not according to their order, but according to their keys. Its more like: I need to search for specific keywords in the dictionary and to save their corresponding values to the variables. For instance, on one update it's keys are:
>>> len(dict.keys())
>>> 30
on another update:
>>> len(dict.keys())
>>> 26
This shows the number of items in the dictionary keeps variating. However, I have noted a list of some obligatory keys (that I am mentioning below) which are always there so I just need to look for them whenever the thing is updated. In more precise terms, I need a way to extract specific keys (probably by searching) and their corresponding values from the dictionary and to save both them to different variables so that I can save them to database. The keys to be searched are:
temp_f
relative_humidity
wind_dir
pressure_mb
location
Thanks.
If I understood your problem well, you don't need to maintain the order of keys/values in your dictionary and you just want to strip your dictionary from unwanted keys and rename the keys you are interested in. Your concern is that some keys might also be missing. I would solve it in this way.
new_dict = {
'tf' : original_dict.get('temp_f', None),
'rh' : original_dict.get('relative_humidity', None),
# And so on...
}
If you want to maintain the order, use collections.OrderedDict instead of normal dict.

Categories