How to reorder a python ordered dict based on array? - python

Say I have an Ordered Dict with the following items:
mydict = {'Rust': {'definition':'rusts definition'}, 'Iron': {'definition:'iron definition'}, 'Pyrite': {'definition':'pyrite definition'}}
If I have an array:
myorder = ['Pyrite', 'Rust', 'Iron']
How can I reorder the Ordered Dict such that the items in mydict are ordered based on myorder?

Try this:
mydict = {'Rust': {'definition':'rusts definition'},
'Iron': {'definition':'iron definition'},
'Pyrite': {'definition':'pyrite definition'}}
myorder = ['Pyrite', 'Rust', 'Iron']
from collections import OrderedDict
ordered = OrderedDict()
for k in myorder:
ordered[k] = mydict[k]
Or even shorter:
ordered = OrderedDict((k, mydict[k]) for k in myorder)
Using the above snippet, ordered will contain the same keys/values as mydict, but they'll be inserted in the same order specified by myorder. That's the advantage of OrderedDict: when iterating over it, it'll preserve the insertion order.
There's no way to sort the existing dictionary in-place (well, you could extract all the key-value pairs, eliminate them and add them again in the correct order, but that's not the idea, is it?), it's necessary to create a new one ... or simply iterate over the existing dictionary in the specified order:
for k in myorder:
x = mydict[k] # do something with x

If you would like to use them in that order, you can do this, for example.
for key in myorder:
value = mydict[key]
print value
Outputs:
{'definition': 'pyrite definition'}
{'definition': 'rusts definition'}
{'definition': 'iron definiti

Related

how to combine the common key and join the values in the dictionary python

I have one list which contain a few dictionaries.
[{u'TEXT242.txt': u'work'},{u'TEXT242.txt': u'go to work'},{u'TEXT1007.txt': u'report'},{u'TEXT797.txt': u'study'}]
how to combine the dictionary when it has the same key. for example:
u'work', u'go to work'are under one key:'TEXT242.txt', so that i can remove the duplicated key.
[{u'TEXT242.txt': [u'work', u'go to work']},{u'TEXT1007.txt': u'report'},{u'TEXT797.txt': u'study'}]
The setdefault method of dictionaries is handy here... it can create an empty list when a dictionary key doesn't exist, so that you can always append the value.
dictlist = [{u'TEXT242.txt': u'work'},{u'TEXT242.txt': u'go to work'},{u'TEXT1007.txt': u'report'},{u'TEXT797.txt': u'study'}]
newdict = {}
for d in dictlist:
for k in d:
newdict.setdefault(k, []).append(d[k])
from collections import defaultdict
before = [{u'TEXT242.txt': u'work'},{u'TEXT242.txt': u'go to work'},{u'TEXT1007.txt': u'report'},{u'TEXT797.txt': u'study'}]
after = defaultdict(list)
for i in before:
for k, v in i.items():
after[k].append(v)
out:
defaultdict(list,
{'TEXT1007.txt': ['report'],
'TEXT242.txt': ['work', 'go to work'],
'TEXT797.txt': ['study']})
This technique is simpler and faster
than an equivalent technique using dict.setdefault()

create ordered dict from list comprehension?

Here is a list comprehension:
L = [{k: d[k](v) for (k, v) in l.iteritems()} for l in L]
where
L is a list of ordered dictionaries (i.e. objects of collections.OrderedDict), where the dictionaries have the same set of keys.
d is another ordered dictionary, which also has the same set of keys as the previous ordered dictionaries.
For each key, d[key] is a function which can apply to L[i][key], i.e. d[key](L[i][key]).
All the given dictionaries are ordered dicts, and have the same order in their keys.
But the code will create an unordered dictionary. How can I create an ordered dict in the same key order as the given ordered dictionaries?
collections.OrderedDict is nothing but a dict, which remembers the order in which the elements are included in it. So you can create one with its constructor like this
[OrderedDict((k, d[k](v)) for (k, v) in l.iteritems()) for l in L]
Python dictionary unlike C++ dictionary are unordered because it uses hash for its keys. Analternative would be to use an ordered specialization of python dictionary called collections.OrdredDict.
This would turn your declaration as
from collections import OrderedDict
L = [OrderedDict((k, d[k](v)) for (k, v) in l.iteritems()) for l in L]

Merging two dictionaries with order saving

I have two dictionaries:
a = {u'Anthracite': [u'3/optimized/8593793_fpx.tif'],
u'Black': [u'6/optimized/8593796_fpx.tif'],
u'Cobalt': [u'9/optimized/8593799_fpx.tif'],
u'Fire': [u'2/optimized/8593802_fpx.tif'],
u'Fuschia': [u'5/optimized/8593805_fpx.tif'],
u'Iris': [u'8/optimized/8593808_fpx.tif'],
u'Midnight': [u'1/optimized/8593811_fpx.tif']}
b = {u'Anthracite': [u'5/optimized/8593795_fpx.tif'],
u'Black': [u'8/optimized/8593798_fpx.tif'],
u'Cobalt': [u'1/optimized/8593801_fpx.tif'],
u'Fire': [u'4/optimized/8593804_fpx.tif'],
u'Fuschia': [u'7/optimized/8593807_fpx.tif'],
u'Iris': [u'0/optimized/8593810_fpx.tif'],
u'Midnight': [u'3/optimized/8593813_fpx.tif']}
I need to produce such dict:
c = {u'Anthracite': [u'3/optimized/8593793_fpx.tif', u'5/optimized/8593795_fpx.tif'],
u'Black': [u'6/optimized/8593796_fpx.tif', u'8/optimized/8593798_fpx.tif'],
....
}
So I need to collect all items from lists with same keys, but I need to save first order.
Dictionaries always have same keys
I have try to do this with zip but I`m getting total mess
Why not just iterating over the dictionaries and copy them to a new dictionary? A defaultdict is used in the following code for simplicity :
from collections import defaultdict
c = defaultdict(list)
a = {"foo": ["bar"]}
b = {"foo": ["baz"], "bah": ["foo"]}
for k, v in a.items() + b.items():
c[k].extend(v)
If the keys are the same, you can copy the first dictionary and update its content :
d = a.copy()
for k, v in b.iteritems():
d[k].extend(v)
Note that the latter creates a shallow copy and therefore the dictionary a is also modified during the process.
If you want alphabetical order, use an OrderedDict and sort the keys:
from collections import OrderedDict
srt_keys = sorted(a.keys())
d = OrderedDict()
for k in srt_keys:
d[k] = a[k]
d[k] += b[k]
print d
OrderedDict([(u'Anthracite', [u'3/optimized/8593793_fpx.tif', u'5/optimized/8593795_fpx.tif']), (u'Black', [u'6/optimized/8593796_fpx.tif', u'8/optimized/8593798_fpx.tif']), (u'Cobalt', [u'9/optimized/8593799_fpx.tif', u'1/optimized/8593801_fpx.tif']), (u'Fire', [u'2/optimized/8593802_fpx.tif', u'4/optimized/8593804_fpx.tif']), (u'Fuschia', [u'5/optimized/8593805_fpx.tif', u'7/optimized/8593807_fpx.tif']), (u'Iris', [u'8/optimized/8593808_fpx.tif', u'0/optimized/8593810_fpx.tif']), (u'Midnight', [u'1/optimized/8593811_fpx.tif', u'3/optimized/8593813_fpx.tif'])])
How about using OrderedDict with a tuple list to set initial order. and then simply maintaining it.
Check my answer here for nicer dict syntax: Override the {...} notation so i get an OrderedDict() instead of a dict()?
from collections import OrderedDict
#Use an ordered dict, with a tuple list init to maintain initial order
a = OrderedDict([
(u'Anthracite', [u'3/optimized/8593793_fpx.tif']),
(u'Black', [u'6/optimized/8593796_fpx.tif']),
(u'Cobalt', [u'9/optimized/8593799_fpx.tif']),
(u'Fire', [u'2/optimized/8593802_fpx.tif']),
(u'Fuschia', [u'5/optimized/8593805_fpx.tif']),
(u'Iris', [u'8/optimized/8593808_fpx.tif']),
(u'Midnight', [u'1/optimized/8593811_fpx.tif'])
])
#We don't care about b's order
b = {u'Anthracite': [u'5/optimized/8593795_fpx.tif'],
u'Black': [u'8/optimized/8593798_fpx.tif'],
u'Cobalt': [u'1/optimized/8593801_fpx.tif'],
u'Fire': [u'4/optimized/8593804_fpx.tif'],
u'Fuschia': [u'7/optimized/8593807_fpx.tif'],
u'Iris': [u'0/optimized/8593810_fpx.tif'],
u'Midnight': [u'3/optimized/8593813_fpx.tif']}
merge = OrderedDict()
#Since b has the same keys as a(we don't need to care for diffrent keys), but we want a's order
for key in a:
#We insert by order to an OrderedDict so the same order will be maintained
merge[key] = a[key] + b[key]

Sort dictionary by specific order (list of keys)

I am trying to sort a dictionary based on the order that its keys appears in a list.
First element of the list would be the first element of the dictionary. At the end the dictionary keys wiould be in the same order as in the provided list...
I can sort by value with this code
newlist = sorted(product_list, key=lambda k: k['product'])
but cant do it for a list
thanks for any help!
from collections import OrderedDict
new_dict = OrderedDict((k, old_dict[k]) for k in key_list)
Having said that, there's probably a better way to solve your problem than using an OrderedDict
If some keys are missing, you'll need to use one of
new_dict = OrderedDict((k, old_dict.get(k)) for k in key_list)
or
new_dict = OrderedDict((k, old_dict[k]) for k in key_list if k in old_dict)
depending on how you want to handle the missing keys.
In Python (and most languages) dictionaries are unsorted, so you can't "sort" a dictionary.
You can retrieve and sort the keys and iterate through those:
for key in sorted(product_list.keys()):
item = product_list[key]
item.doSomething()
Or you can use a OrderDict, like so:
from collections import OrderedDict
And then build the dictionary in the required order (which is up to you to determine) but below we sort using the keys:
product_list = OrderDict(sorted(product_list.items(), key=lambda k: k[0]))
For reference, Dict.items() returns a list of tuples in the form:
[(key1, value1), (key2, value2) , ... , (keyN, valueN)]
By definition, a dictionary is unordered. You can use OrderedDict from collections as seen at http://docs.python.org/2/library/collections.html#collections.OrderedDict as a drop-in replacement.

Selecting dictionary items by key efficiently in Python

suppose I have a dictionary whose keys are strings. How can I efficiently make a new dictionary from that which contains only the keys present in some list?
for example:
# a dictionary mapping strings to stuff
mydict = {'quux': ...,
'bar': ...,
'foo': ...}
# list of keys to be selected from mydict
keys_to_select = ['foo', 'bar', ...]
The way I came up with is:
filtered_mydict = [mydict[k] for k in mydict.keys() \
if k in keys_to_select]
but I think this is highly inefficient because: (1) it requires enumerating the keys with keys(), (2) it requires looking up k in keys_to_select each time. at least one of these can be avoided, I would think. any ideas? I can use scipy/numpy too if needed.
dict((k, mydict[k]) for k in keys_to_select)
if you know all the keys to select are also keys in mydict; if that's not the case,
dict((k, mydict[k]) for k in keys_to_select if k in mydict)

Categories

Resources