How to filter list of dictionaries with matching values for a given key
16,882
Solution 1
Update: taking into account the reedited question of the OP:
def copyf(dictlist, key, valuelist):
return [dictio for dictio in dictlist if dictio[key] in valuelist]
Solution 2
Probably not the best solution, but here we go:
>>> def copyf(data, key, allowed):
... return filter(lambda x: key in x and x[key] in allowed, data)
...
>>> dictlist = [{'first': 'James', 'last': 'Joule'}, {'first': 'James','last': 'Watt'},{'first': 'Christian','last': 'Doppler'}]
>>> copyf(dictlist, 'first', ('Christian',))
[{'last': 'Doppler', 'first': 'Christian'}]
>>> copyf(dictlist, 'last', ('Christian',))
[]
>>> copyf(dictlist, 'first', ('James',))
[{'last': 'Joule', 'first': 'James'}, {'last': 'Watt', 'first': 'James'}]
>>>
Solution 3
Something like
new_dict = dict((k, v) for k,v in old_dict.items() if v in allowed_values)
?
Solution 4
Clean and neat, using filter and lambda
>>> def copyf(dictlist, key, valuelist):
... filter(lambda d: d[key] in valuelist, dictlist)
Comments
-
Christopher O'Donnell almost 2 years
With an interface like
a = copyf(dictlist, key, valuelist)
.>>> dictlist = [{'first': 'James', 'last': 'Joule'}, {'first': 'James', 'last': 'Watt'}, {'first': 'Christian', 'last': 'Doppler'}] >>> valuelist = ['James', 'John'] >>> x = copyf(dictlist, 'first', valuelist) >>> print(x) [{'first': 'James', 'last': 'Joule'}, {'first': 'James', 'last': 'Watt'}]
The
dictlist
is effectively acsv.DictReader
instance. -
kevpie about 13 years@plaes, you can turn the list comprehension into a generator expression by dropping the square brackets. This is in keeping with what your usage of iteritems() is trying to accomplish by avoiding the creation of an intermediate list.
-
plaes about 13 years@kevpie: Thanks, will fix \o/
-
joaquin about 13 yearsyou are removing all coincident values indepently of the key. The OP question said "matching values (for a given key) from a list" and actually gave 'key' as a function parameter. Maybe he changed his mind...or I misunderstood?
-
9000 about 13 yearsin a dict, there can only be 0 or 1 value per given key. this sort of distracted me from the phrase you boldfaced. sorry! :)
-
joaquin about 13 yearsWell, you got the "accepted answer". Hope it is not due homework :-))
-
9000 about 13 yearsAccepted answers change sometimes. Statistically it pays to give a superior answer even if the question already has a low-scored accepted answer (like mine here). Note that a fuller answer with the same approach now scores twice as high.
-
joaquin about 13 years@plaes, probably the OP was asking to filter by values not by keys. Note the function parameters given (dictionary, key, valuelist).
-
plaes about 13 years@joaquin: Now that I look it again, it might be like that. :S
-
Christopher O'Donnell about 13 yearsSorry guys, I was super tired when I posted the question and accepted this answer. This doesn't take "for a given key" into consideration.
-
Christopher O'Donnell about 13 yearsSorry for the ambiguity, I have provided a usage example.
-
9000 about 13 yearsIt's totally ok. The right answer ought to be accepted, and a wrong answer, no matter how much upvoted, ought not.