In list of dicts, match dict based on one key/value?
In Python, I have a list of dictionaries:
mylist = [ { 'name': 'James', 'school': 'UCLA', 'date_joined': 2001 },
{ 'nam开发者_JAVA百科e': 'Jack', 'school': 'UCLA', 'date_joined': 2001 },
{ 'name': 'Fisher', 'school': 'NYU', 'date_joined': 2003 }]
How can I check whether a certain dictionary matches existing record, based only on the name and school key/values?
So:
example1 = { 'name': 'James', 'school': 'UCLA', 'date_joined': 2007 }
example1 = { 'name': 'James', 'school': 'UCLA', 'date_joined': 2001 }
should both match, but
example3 = { 'name': 'James', 'school': 'MIT', date_joined': 2001 }
should not.
There's obviously:
for m in myList:
if (m['name']==example['name'] and m['school']==example['school']):
match_found = True
continue
but is there a more compact way?
fields = ('name', 'school')
match_found = any(all(x[f]==example[f] for f in fields) for x in myList)
Not knowing anything more about the structure of your program, my approach might be somewhat different:
from collections import namedtuple
import datetime
StudentRecord = namedtuple('StudentRecord', 'name school date_joined')
myset = set([StudentRecord('James', 'UCLA', 2001),
StudentRecord('Jack', 'UCLA', 2001),
StudentRecord('Fisher', 'NYU', 2003)])
this_year = datetime.datetime.today().year
match_found = any(StudentRecord('James', 'UCLA', year) in myset for year in range(1950, this_year))
This will be slower for very small lists because it has to check for every year, but for lists of thousands of students, none of whom entered school before 1950, this will be much faster. It's O(n) in the number of years, while the list approach is O(n) in the number of students, and the number of years will probably grow much more slowly than the number of students. (It does require that no records are identical though -- but then, you probably want that anyway. Alternatively, you could always use a dict of lists instead of a set to handle collisions.)
Also, for a truly constant time algorithm you could do this, using a list of years for multiple identical student listings, which also addresses the problem of collisions:
StudentRecord = namedtuple('StudentRecord', 'name school')
mydict = {StudentRecord('James', 'UCLA'):[2001],
StudentRecord('Jack', 'UCLA') :[2001],
StudentRecord('Fisher', 'NYU'):[2003, 2007]}
match_found = StudentRecord('James', 'UCLA') in mydict
if all(m[k]==example[k] for k in ('school','name'))
精彩评论