Home > Net >  Trying to filter a list of dicts by the content of a nested list, but getting the same list of dicts
Trying to filter a list of dicts by the content of a nested list, but getting the same list of dicts

Time:11-27

I have a list of dictionaries with the following stucture:

list_of_dicts = [
        {'id': 1, 'fruits':['apple']},
        {'id': 2, 'fruits':['orange']},
        {'id': 3, 'fruits':['banana', 'apple']},
        {'id': 4, 'fruits':['banana', 'apple', 'orange']}
        ]

I want to filter the list_of_dicts by the elements contained in the 'fruits' keys. Specifically, I want to compare the fruits a list of acceptable fruits:

acceptable_fruits = ['apple', 'banana']

the expected result of this filter should be a list like this:

expected_result = [
        {'id': 1, 'fruits':['apple']},
        {'id': 3, 'fruits':['banana', 'apple']},
        {'id': 4, 'fruits':['banana', 'apple', 'orange']}]

I have attempted to nested filter statements, but that does not seem to work:

filtered_list = filter(lambda dict: filter(lambda fruit: fruit in acceptable_fruits, dict['fruits']), list_of_dicts)

The return in this case is the original list:

print(list(filtered_list))

returns:

[{'id': 1, 'fruits': ['apple']}, {'id': 2, 'fruits': ['orange']}, {'id': 3, 'fruits': ['banana', 'apple']}, {'id': 4, 'fruits': ['banana', 'apple', 'orange']}]

Other iterating loops have not worked well for me either. Does anybody have a good way of doing this?

CodePudding user response:

The problem is that filter doesn't return a list in Python 3. Obviously, you're handling that for the outer filter with list(filtered_list), but the inner filter is not handled, so it's evalutating as True, like this:

>>> f = filter(None, [])
>>> bool(f)
True

To fix it, you could just wrap the inner filter in list(), but really what you're trying to ask is "is any fruit in acceptable_fruits?", which is better written with any(). And besides, list(filter(lambda)) is better written as a comprehension, for both inner and outer:

filtered_list = [
    d for d in list_of_dicts
    if any(fruit in acceptable_fruits for fruit in d['fruits'])]

Result:

[{'id': 1, 'fruits': ['apple']},
 {'id': 3, 'fruits': ['banana', 'apple']},
 {'id': 4, 'fruits': ['banana', 'apple', 'orange']}]

CodePudding user response:

can be easy with sets

list_of_dicts = [
        {'id': 1, 'fruits':{'apple'}},
        {'id': 2, 'fruits':{'orange'}},
        {'id': 3, 'fruits':{'banana', 'apple'}},
        {'id': 4, 'fruits':{'banana', 'apple', 'orange'}}
        ]
        
acceptable_fruits = {'apple', 'banana'}

result=[d for d in list_of_dicts if acceptable_fruits & d['fruits']]
print(result)
>>> [{'id': 1, 'fruits': {'apple'}}, {'id': 3, 'fruits': {'banana', 'apple'}}, {'id': 4, 'fruits': {'banana', 'apple', 'orange'}}]
  • Related