DominiCane
DominiCane

Reputation: 1303

Filter list of dictionaries by nested attributes

I have the current list I'd like to filter by type=orange:

my_list = [{'anotherfieds': 'aaa',
  'fruits': [{'tastes': 'good', 'type': 'orange'},
             {'tastes': 'bad', 'type': 'apple'}],
  'name': 'A'},
 {'differentfield': 'bbb',
  'fruits': [{'tastes': 'so-so', 'type': 'orange'},
             {'tastes': 'good', 'type': 'banana'}],
  'name': 'B'},
 {'fruits': [{'tastes': 'good', 'type': 'avocado'},
             {'tastes': 'yes', 'type': 'lemon'}],
  'name': 'C',
  'somethingelse': 'ccc'}]

As an output I'd like to have all dictionaries that have type equal to orange in their attributes, so output is expected like following:

[{'anotherfieds': 'aaa',
  'fruits': [{'tastes': 'good', 'type': 'orange'},
             {'tastes': 'bad', 'type': 'apple'}],
  'name': 'A'},
 {'differentfield': 'bbb',
  'fruits': [{'tastes': 'so-so', 'type': 'orange'},
             {'tastes': 'good', 'type': 'banana'}],
  'name': 'B'}]

All the dictionaries always contain list of dictionaries that contain type. The most far I got is this:

jmespath.search('[].fruits[?type==`orange`] []', my_list)

>>> [{'tastes': 'good', 'type': 'orange'}, {'tastes': 'so-so', 'type': 'orange'}]

But I need the whole list elements, like above, not only sub-elements.

How can I filter the list for entire elements having this specific key-value pair?

Upvotes: 1

Views: 415

Answers (1)

hc_dev
hc_dev

Reputation: 9387

See JMESPath documentation: Filter Expressions.

The filter-expression should be:

[?fruits[?type==`orange`]]

to filter al elements of the array or list that have fruits with desired type:

import jmespath

my_list = [{'anotherfieds': 'aaa',
  'fruits': [{'tastes': 'good', 'type': 'orange'},
             {'tastes': 'bad', 'type': 'apple'}],
  'name': 'A'},
 {'differentfield': 'bbb',
  'fruits': [{'tastes': 'so-so', 'type': 'orange'},
             {'tastes': 'good', 'type': 'banana'}],
  'name': 'B'},
 {'fruits': [{'tastes': 'good', 'type': 'avocado'},
             {'tastes': 'yes', 'type': 'lemon'}],
  'name': 'C',
  'somethingelse': 'ccc'}]

elements_with_oranges = jmespath.search('[?fruits[?type==`orange`]]', my_list)
print(elements_with_oranges)

Prints desired 2 of the 3:

[{'anotherfieds': 'aaa', 'fruits': [{'tastes': 'good', 'type': 'orange'}, {'tastes': 'bad', 'type': 'apple'}], 'name': 'A'}, {'differentfield': 'bbb', 'fruits': [{'tastes': 'so-so', 'type': 'orange'}, {'tastes': 'good', 'type': 'banana'}], 'name': 'B'}]

Upvotes: 2

Related Questions