Python3: Conditional extraction of keys from a dictionary with comprehension - python

I need to extract those keys of a dictionary whose values pass a certain condition.
Basically, I want to do this, only in a shorter, more pythony way:
keys=[]
for key in dict:
if dict[key]==True:
keys.append(key)
This was my original idea, but it raises a ValueError:
[key for (key,val) in map if val==True]
I came up with this for the moment, but I can't help feeling it's not very nice:
[key for key in map.keys() if map[key]==True]
Is there a less messy way to it? Perhaps something obvious that I'm clearly missing?
Thanks!

Here is a way to get the keys with true values that is a lot shorter and cleaner than a comprehension (not that comprehensions are bad though):
>>> dct = {0:False, 1:True, 2:False, 3:True}
>>> list(filter(dct.get, dct))
[1, 3]
>>>

Use dict.items()
[key for key, val in dct.items() if val]
If you want to take only the keys with True values, rather than any true-ish value, you can use an equality check:
[key for key, val in dct.items() if val==True]
It is noted in PEP8 though, that one shouldn't compare boolean values using == - so don't use it unless you absolutely need to.
Also, please don't name variables dict or map (even if it's for demonstration purposes only) because they shadow the bulitins.

Iterating over a mapping yields only keys. Use map.items() instead.

Related

convert for loop into dictionary comprehension

I have a small program that works just fine. I am trying to force myself to review\analyze my code in order to try to make my code (and myself) just a little better.
I was wondering if this small portion of code:
temp2 = {}
for key in sorted(temp1.keys()):
temp2[key] = temp1[key]
couldn't be rewritten as a dictionary comprehension.
Due primarily to my profound lack of experience I am not able to 'convert'
this into a comprehension.
All the loop does is take dictionary temp1, sort it and place the newly sorted key:value pairs into temp2.
As I stated above, the whole thing works as is, but I am trying to learn
spotting patterns where I can make improvements.
Directly translating this to a dictionary comprehension is easy:
temp2 = {key: value for key, value in sorted(temp1.items())}
In case you don't want to use the value as tie-breaker if the keys are equal you could also provide a key so you're only sorting based on the key:
temp2 = {key: value for key, value in sorted(temp1.items(), key=lambda x: x[0])}
Even though dictionaries are "ordered" in python-3.6 doesn't mean you should rely on it (the orderedness is officially just a side-effect!). Better to use an OrderedDict and be on the safe side:
from collections import OrderedDict
temp2 = OrderedDict([(key, value) for key, value in sorted(temp1.items(), key=lambda x: x[0])])

Check if any of the list of keys are present in a dictionary [duplicate]

This question already has an answer here:
Check if items in a list exist in dictionary
(1 answer)
Closed 7 years ago.
I have a fixed list of strings. I need to check if any of these strings are a key in the dictionary (just need True or False). I could go
if 'asdf' in dict or 'qwer' in dict or 'zxcv' in dict ... :
... do important secret stuff ...
but it seems suboptimal. Is there a more idiomatic way of doing this?
You could use any and iterate over each key you want to check
if any(key in dict for key in ['asdf', 'qwer', 'zxcf']):
# contains at least one of them
This will short-circuit and return True upon finding the first match, or will return False if it finds none.
You could also use &:
keys = ['asdf', 'qwer', 'zxcf']
if d.keys() & keys:
print(d)
You would need d.viewkeys() for python2.
Alternatively, make keys a set and see if the set is disjoint or not, which will be the fastest approach:
keys = {'asdf', 'qwer', 'zxcf'}
if not keys.isdisjoint(d):
print(d)
you could try using list comprehension in python:
if any([True for entry in your_list if entry in dict]):
--dostuff--
EDIT: CoryKramer suggested to remove the '[]' in order to make this a generator, rather than evaluate the entire list before checking if any elements are "True":
if any(True for entry in your_list if entry in dict):
--dostuff--

What's the fastest way to identify the 'name' of a dictionary that contains a specific key-value pair?

I'd like to identify the dictionary within the following list that contains the key-value pair 'Keya':'123a', which is ID1 in this case.
lst = {ID1:{'Keya':'123a','Keyb':456,'Keyc':789},ID2:{'Keya':'132a','Keyb':654,'Keyc':987},ID3:{'Keya':'5433a','Keyb':222,'Keyc':333},ID4:{'Keya':'444a','Keyb':777,'Keyc':666}}
It's safe to assume all dictionaries have the same key's, but have different values.
I currently have the following to identify which dictionary has the value '123a' for the key 'Keya', but is there a shorter and faster way?
DictionaryNames = map(lambda Dict: str(Dict),lst)
Dictionaries = [i[1] for i in lst.items()]
Dictionaries = map(lambda Dict: str(Dict),Dictionaries)
Dict = filter(lambda item:'123a' in item,Dictionaries)
val = DictionaryNames[Dictionaries.index(Dict[0])]
return val
If you actually had a list of dictionaries, this would be:
next(d for d in list_o_dicts if d[key]==value)
Since you actually have a dictionary of dictionaries, and you want the key associated with the dictionary, it's:
next(k for k, d in dict_o_dicts.items() if d[key]==value)
This returns the first matching value. If you're absolutely sure there is exactly one, or if you don't care which you get if there are more than one, and if you're happy with a StopIteration exception if you were wrong and there isn't one, that's exactly what you want.
If you need all matching values, just do the same with a list comprehension:
[k for k, d in dict_o_dicts.items() if d[key]==value]
That list can of course have 0, 1, or 17 values.
You can just do [name for name, d in lst.iteritems() if d['Keya']=='123a'] to get a list of all the dictionaries in lst that have that value for that key. If you know there is only one, you can get it with [name for name, d in lst.iteritems() if d['Keya']=='123a'][0]. (As Andy mentions in a comment, your name lst is misleading, since lst is actually a dictionary of dictionaries, not a list.)
Since you want the fastest, you should short-cut your search as soon as you find the data you are after. Iterating through the whole list is not necessary, nor is producing any temporary dictionary:
for key,data in lst.iteritems():
if data['Keya']=='132a':
return key #or break is not in a function
Å different way to do this is to use the appropriate data structure: Keep a "reverse map" of key-value pairs to names. If your dictionary of dictionaries is static after being built, you can build the reverse dictionary like this:
revdict = {(key, value): name
for name, subdict in dictodicts.items()
for key, value in subdict.items()}
If not, you just need to add revdict[key, value] = name for each d[name][key] = value statement and build them up in parallel.
Either way, to find the name of the dict that maps key to value, it's just:
revdict[key, value]
For (a whole lot) more information (than you actually want), and some sample code for wrapping things up in different ways… I dug up an unfinished blog post, considered editing it, and decided to not bother and just clicked Publish instead, so: Reverse dictionary lookup and more, on beyond z.

Using python to match the values in a dictionary's array with an original value

I have the following in a dictionary:
"key": ["array_value1", "array_value2", "array_value3"],
I have another value I'd like to check against one of the values in the array in an if-else statement. For example:
if checkedValue == array_value1:
#something happens
I don't know how to iterative over the values in "key" so that it automatically checks for the values inside it.
You could do something like
if checkedValue in dict_name['key']:
#do something
Dictionary values have a type, just like anything else. It looks like your dictionary value in this case is an array, so iterate over it in the same way as you iterate over any other iterable collection:
for val in mydict["key"]:
if checkedValue == val:
doSomething
As pointed out in nickflees's answer, the array type works well with the in keyword, but this is just syntactic sugar for iterating through the array until you find the desired value. The point is that dictionary values are not "special" types in any way; mydict["key"] is just a reference to whatever you've stored under that key in the dictionary.
Another way using any.
for k, v in dy.iteritems():
if any(val == checkValue for val in v):
print "something happens"
For Python 3, use items instead of iteritems.

How to print dictionary's values from left to right?

I have a dictionary:
a = {"w1": "wer", "w2": "qaz", "w3": "edc"}
When I try to print its values, they are printed from right to left:
>>> for item in a.values():
print item,
edc qaz wer
I want them to be printed from left to right:
wer qaz edc
How can I do it?
You can't. Dictionaries don't have any order you can use, so there's no concept of "left to right" with regards to dictionary literals. Decide on a sorting, and stick with it.
You can use collections.OrderedDict (python 2.7 or newer -- There's an ActiveState recipe somewhere which provides this functionality for python 2.4 or newer (I think)) to store your items. Of course, you'll need to insert the items into the dictionary in the proper order (the {} syntax will no longer work -- nor will passing key=value to the constructor, because as others have mentioned, those rely on regular dictionaries which have no concept of order)
Assuming you want them in alphabetical order of the keys, you can do something like this:
a = {"w1": "wer", "w2": "qaz", "w3": "edc"} # your dictionary
keylist = a.keys() # list of keys, in this case ["w3", "w2", "w1"]
keylist.sort() # sort alphabetically in place,
# changing keylist to ["w1", "w2", w3"]
for key in keylist:
print a[key] # access dictionary in order of sorted keys
as #IgnacioVazquez-Abrams mentioned, this is no such thing as order in dictionaries, but you can achieve a similar effect by using the ordered dict odict from http://pypi.python.org/pypi/odict
also check out PEP372 for more discussion and odict patches.
Dictionaries use hash values to associate values. The only way to sort a dictionary would look something like:
dict = {}
x = [x for x in dict]
# sort here
y = []
for z in x: y.append(dict[z])
I haven't done any real work in python in a while, so I may be a little rusty. Please correct me if I am mistaken.

Categories

Resources