Skip to content Skip to sidebar Skip to footer

Pythonic Way To Compare Values In Two Lists Of Dictionaries

I'm new to Python and am still trying to tear myself away from C++ coding techniques while in Python, so please forgive me if this is a trivial question. I can't seem to find the

Solution 1:

Suppose your lists are called l1 and l2:

All elements from l1:

[eachforeach in l1]

All elements from l1 with the Restaurant category:

[eachforeach in l1
      if'Restaurants' in each['categories']]

All elements from l2 matching id with elements from l1 with the Restaurant category:

[xforeach in l1 forx in l2 
   if'Restaurants' in each['categories']
   andx['business_id'] == each['business_id'] ]

Solution 2:

Let's define sample lists of dictionaries:

first = [
        {'business_id':100, 'categories':['Restaurants']},
        {'business_id':101, 'categories':['Printer']},
        {'business_id':102, 'categories':['Restaurants']},
        ]

second = [
        {'business_id':100, 'stars':5},
        {'business_id':101, 'stars':4},
        {'business_id':102, 'stars':3},
        ]

We can extract the items of interest in two steps. The first step is to collect the list of business ids that belong to restaurants:

ids = [d['business_id'] for d in first if 'Restaurants' in d['categories']]

The second step is to get the dicts that correspond to those ids:

[d for d in second if d['business_id'] in ids]

This results in:

[{'business_id': 100, 'stars': 5}, {'business_id': 102, 'stars': 3}]

Solution 3:

Python programmers like using list comprehensions as a way to do both their logic and their design.

List comprehensions lead to terser and more compact expression. You're right to think of it quite a lot like a query language.

x = [comparison(a, b) for (a, b) in zip(A, B)] 
x = [comparison(a, b) for (a, b) in itertools.product(A, B)] 
x = [comparison(a, b) for a in A for b in B if test(a, b)]
x = [comparison(a, b) for (a, b) in X for X in Y if test(a, b, X)]

...are all patterns that I use.

Solution 4:

This is pretty tricky, and I had fun with it. This is what I'd do:

defmatch_fields(business, review):
    return business['business_id'] == review['business_id'] and'Restaurants'in business['categories']

defsearch_businesses(review):
    # the lambda binds the given review as an argument to match_fieldsreturnany(lambda business: match_fields(business, review), business_list)

answer = filter(search_businesses, review_list)

This is the most readable way I found. I'm not terribly fond of list comprehensions that go past one line, and three lines is really pushing it. If you want this to look more terse, just use shorter variable names. I favor long ones for clarity.

I defined a function that returns true if an entry can be matched between lists, and a second function that helps me search through the review list. I then can say: get rid of any review that doesn't have a matching entry in the businesses list. This pattern works well with arbitrary checks between lists.

Solution 5:

As a variation to the list comprehension only approaches, it may be more efficient to use a set and generator comprehension. This is especially true if the size of your first list is very large or if the total number of restaurants is very large.

restaurant_ids = set(biz for biz in first if 'Restaurants' in biz['categories'])
restaurant_data = [rest for rest in second if rest['id'] in restaurant_ids]

Note the brute force list comprehension approach is O(len(first)*len(second)), but it uses no additional memory storage whereas this approach is O(len(first)+len(second)) and uses O(number_of_restaurants) extra memory for the set.

Post a Comment for "Pythonic Way To Compare Values In Two Lists Of Dictionaries"