Selecting dictionary items by key efficiently in Python - 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)

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]

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.

How to reorder a python ordered dict based on array?

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

Refactoring with python dictionary comprehension

I have 2 dictionary which contain the same keys but the value pairs are different. Let's make dictA and dictB represent the two dictionaries in question.
dictA = {'key1':'Joe', 'key2':'Bob'}
dictB = {'key1':'Smith', 'key2':'Johnson'}
Currently, I am creating a new dictionary based the common occurring keys through a nested if statement. In doing so, the values that share a key are contained within a list, in the new dictionary. See this done below:
dictAB = {} # Create a new dictionary
# Create a list container for dictionary values
for key in dictA.keys():
dictAB[key] = []
# Iterate through keys in both dictionaries
# Find matching keys and append the respective values to the list container
for key, value in dictA.iteritems():
for key2, value2 in dictB.iteritems():
if key == key2:
dictAB[key].append(value)
dictAB[key].append(value2)
else:
pass
How can this be made into a more clean structure using python dictionary comprehension?
Use sets or key views (python 2.7):
dictAB = {k: [dictA[k], dictB[k]] for k in dictA.viewkeys() & dictB.viewkeys()}
Before 2.7:
dictAB = dict((k, [dictA[k], dictB[k]]) for k in set(dictA) & set(dictB))
In python 3, you can use the .keys method for such operations directly, as they are implemented as views:
dictAB = {k: [dictA[k], dictB[k]] for k in dictA.keys() & dictB.keys()}
Demo (python 2.7):
>>> dictA = {'key1':'Joe', 'key2':'Bob'}
>>> dictB = {'key1':'Smith', 'key2':'Johnson'}
>>> dictAB = {k: [dictA[k], dictB[k]] for k in dictA.viewkeys() & dictB.viewkeys()}
>>> print dictAB
{'key2': ['Bob', 'Johnson'], 'key1': ['Joe', 'Smith']}
The & operator on either two sets or on a dict view creates the intersection of both sets; all keys that are present in both sets.
By using an intersection of the keys, this code will work even if either dictA or dictB has keys that do not appear in the other dictionary. If you are absolutely sure the keys will always match, you could just iterate over either dict directly without the intersection:
dictAB = {k: [dictA[k], dictB[k]] for k in dictA}
dictAB = { key: [dictA[key],dictB[key]] for key in dictA if key in dictB }

Categories

Resources