I am trying to create a new dict using a list of values of an existing dict as individual keys.
So for example:
dict1 = dict({'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]})
and I would like to obtain:
dict2 = dict({1:['a','b','c'], 2:['a','b','c'], 3:['a','b'], 4:['b']})
So far, I've not been able to do this in a very clean way. Any suggestions?
If you are using Python 2.5 or above, use the defaultdict class from the collections module; a defaultdict automatically creates values on the first access to a missing key, so you can use that here to create the lists for dict2, like this:
from collections import defaultdict
dict1 = dict({'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]})
dict2 = defaultdict(list)
for key, values in dict1.items():
for value in values:
# The list for dict2[value] is created automatically
dict2[value].append(key)
Note that the lists in dict2 will not be in any particular order, as a dictionaries do not order their key-value pairs.
If you want an ordinary dict out at the end that will raise a KeyError for missing keys, just use dict2 = dict(dict2) after the above.
Notice that you don't need the dict in your examples: the {} syntax gives you a dict:
dict1 = {'a':[1,2,3], 'b':[1,2,3,4], 'c':[1,2]}
Other way:
dict2={}
[[ (dict2.setdefault(i,[]) or 1) and (dict2[i].append(x)) for i in y ] for (x,y) in dict1.items()]
Related
Is there a way to sort all the keys, sub-keys, sub-sub-keys, etc. of a python dictionary at once?
Let's suppose I have the dictionary
dict_1 = {
"key9":"value9",
"key5":"value5",
"key3":{
"key3_1":"value3_1",
"key3_3":"value3_3",
}
"key4":"value4",
"key2":"value2",
"key8":{
"key8_1":"value8_1",
"key8_5":[
"value8_5_3",
"value8_5_1",
]
"key8_2":"value8_2",
}
"key4":"value4",
"key1":"value1",
}
and I want it sorted as
dict_1 = {
"key1":"value1",
"key2":"value2",
"key3":{
"key3_1":"value3_1",
"key3_3":"value3_3",
}
"key4":"value4",
"key5":"value5",
"key8":{
"key8_1":"value8_1",
"key8_2":"value8_2",
"key8_5":[
"value8_5_1",
"value8_5_3",
]
}
"key9":"value9",
}
Is there a method to do it?
Please note:
potentially my dict_1 could have several levels of subkeys (nested
dictionaries) or subvalues (nested lists).
I am using Python 2.7.17, and I cannot update it. But order is not
preserved in dictionaries of Python versions previous to 3.7, so I bet
the sorting has to be done by using the OrderedDict.
First, it is important to know that dictionaries are not ordered. So, if you want to order a dict, you need to go with collections.OrderedDict (which exists since Python 2.7).
And then, this is a use case for a recursive function:
from collections import OrderedDict
def order_dict(d):
ordered_dict = OrderedDict()
for key in sorted(d.keys()):
val = d[key]
if isinstance(val, dict):
val = order_dict(val)
ordered_dict[key] = val
return ordered_dict
I have three dicts say dict_a, dict_b and dict_c
dict_a={'key1':a, 'key2':b, 'key3':c}
dict_b={'key1':a, 'key2':b, 'key4':d}
dict_c={'key3':c, 'key1':a, 'key5':e}
Here the keys that are represented overall are: key1, key2, key3, key4, key5 with their respective values.
What I am looking for is eg., to create a new dict (or keep the dicts) and fill the missing keys in each dict in compare to the overall keys with 0 values and the key e.g,:
dict_a={'key1':a, 'key2':b, 'key3':c, 'key4':0, 'key5':0}
dict_b={'key1':a, 'key2':b, 'key3':0, 'key4':d, 'key5':0}
dict_c={'key1':a, 'key2':b, 'key3':c, 'key4':0, 'key5':e}
I am experienced in C, and based on my "limited knowledge" in python I would run a nested for-loop with a bunch of if, else statement to solve this, however what I know is python have some tools eg. zip, lamda etc. to nail this in a simple way. But I don't know how to start and begin, or even if there is a library that can solve this ?
it doesen't matter if I create new dicts with the missing keys or simple replace the existing dict, both are usable.
You could create a union of your keys and then just create new dictionaries containing all keys that you update with your previous values.
all_keys = set(dict_a).union(dict_b, dict_c)
new_dict_a = dict.fromkeys(all_keys, 0)
new_dict_a.update(dict_a)
print(new_dict_a)
# {'key1': 'a', 'key2': 'b', 'key3': 'c', 'key4': 0, 'key5': 0}
The same for the other dicts:
new_dict_b = dict.fromkeys(all_keys, 0)
new_dict_b.update(dict_b)
new_dict_c = dict.fromkeys(all_keys, 0)
new_dict_c.update(dict_c)
The dict.fromkeys creates a new dictionary containing all the specified keys with a default value (in this case 0) and then the update overwrites the values that were already in the original dictionary.
you could do this:
all_keys = set(dict_a).union(dict_b, dict_c)
default = 0
dct_a = {key: dict_a.get(key, default) for key in all_keys}
print(dct_a) # {'key2': 'b', 'key4': 0, 'key5': 0, 'key1': 'a',
# 'key3': 'c'}
...and so on for the other dicts.
once you have collected all_keys it's just a one-liner to create the new dictionary. dict.get is either the value that belongs to the key - if it exists - or default otherwise.
keys=set(dict_a).union(dict_b, dict_c)
for a in keys:
if a not in dict_a.keys():
dict_a[a]=0
if a not in dict_b.keys():
dict_b[a]=0
if a not in dict_c.keys():
dict_c[a]=0
Using sets to avoid having duplicates, we get all the keys. Now we know all the keys there are. Now we check if any of these keys are not in any of the dicts and if they are not, we add them with the value 0.This will give your desired output
If I have a dict in Python like the following:
d = {'hello': [{a:1, b:2, c:3}, {a:4, b:5, c:6},{a:7, b:8, c:9}]}
I'd like to create an array that will give me all the values of "b". Short of iterating over the array for key "hello", is there an easy way to do this?
Use a list comprehension:
b_list = [subdict[b] for subdict in d['hello']]
Iterate over all the sub-dictionaries in the value stored by hello and access the value stored by the key b.
This is more of a theoretical question than anything. I have 3 dictionaries that have different structure/keys but the values may be the same. E.g.
dict1 = {u'd':{u'results':[{u'number':'1', u'dispURL':u'www.site.com'},
{u'number':u'2', u'dispURL':u'www.othersite.com'}]
}}
dict2 = {u'result_page':{u'url':u'www.greatsite.com', u'pos':u'1'},
{u'url':u'www.site.com', u'pos':u'2'}}
dict3 = {u'hits':[{u'displayurl':u'www.othersite.com', u'index':u'1'},
{u'displayurl':u'www.site.com', u'index':u'2'}]
}
Note how dict1 has {u'd': before the {u'results':, also dict1 and dict3 have the different key/values enclosed in square parentheses. Also note how the keys/values layout is different in dict1 with the number key coming before the url instead of after like in dict2 and dict3, as well as the key names being different in each dictionary.
I have 3 large dictionaries like this and I need to compare them by the position of each url for scoring purposes. i.e.
if dict1[www.site.com index] > dict2[www.site.com index]:
dict1[www.site.com] score +1
I know the code snippet isn't correct it's just for illustration. What I want to know is what do I need to do with the dictionaries to be able to perform a comparison like this? I was thinking of taking the required data from each dictionary and putting them into 3 new dictionaries with uniform keys and structure, or even 1 new dictionary. But my program has to be computationally quite fast so I don't know how this would affect it. Any of you more experienced python programmers want to have a say on this?
The most effective way to approach this is to convert your data into canonical {url:value} format.
For example:
dict1 = {data[u'dispURL']:int(data[u'number']) for data in dict1[u'd'][u'results']}
dict2 = {data[u'url']:int(data[u'pos']) for data in dict2[u'result_page']}
dict3 = {data[u'displayurl']:int(data[u'index']) for data in dict3[u'hits']}
Now they look like
dict1 = {u'www.othersite.com': 2, u'www.site.com': 1}
dict2 = {u'www.greatsite.com': 1, u'www.site.com': 2}
dict3 = {u'www.othersite.com': 1, u'www.site.com': 2}
and your comparison looks like
for url in dict1:
if dict1[url] > dict2[url]:
# do something
If I create a dict of dicts
mydict = {
'zstuff':{
'zzz':True,
'aaa':True
},
'astuff':{
'zzz':True,
'aaa':True
}
}
Then use 'for' to cycle the dicts
for key in mydict:
for tag in mydict[key]:
print "{}:{}".format(key,tag)
Python outputs
zstuff:aaa
zstuff:zzz
astuff:aaa
astuff:zzz
Is there any way to get Python to not re-order the second level dicts?
Python does not order dictionaries alphabetically. In fact, it orders dictionaries arbitrarily. If you need a dictionary object that keeps the original order, have a look at the collections.OrderedDict class available in Python 2.7.
from collections import OrderedDict
mydict = {'zstuff' : OrderedDict(zzz=True, aaa=True),
'astuff' : OrderedDict(zzz=True, aaa=True)}