3

How can I check if a list exists as a value in a dictionary which is a member of a list (list of dictionaries)?

totalList = ([{'score': 1, 'item': ['text1', 'text2']},
              {'score': 2, 'item': ['text3', 'text4']},
              {'score': 3, 'item': ['text5', 'text6']}])
redList = ['text1', 'text2']

A one-liner such as this (though this one doesn't work for obvious reasons). I want to avoid loops.

if redList in totalList:
    print("True")

Context:

redlists = a list of lists
totalList = []
for redlist in redlists:
   if redlist not in totalList:
      totalList.append(dictionary_item))

Example ditcionary_item = {'score': 1, 'item': ['text1', 'text2']}

Note: Total list keeps growing because every time redList is not in the totalList, I add a new dictionary to the toalList based on predefined criteria.

utengr
  • 2,778
  • 20
  • 56
  • Here is a possible duplicate question https://stackoverflow.com/questions/5762643/how-to-filter-list-of-dictionaries-with-matching-values-for-a-given-key – kasravnd Oct 30 '17 at 11:43
  • the dictionary is always the first element of the list, or at the same index ? – PRMoureu Oct 30 '17 at 11:45
  • 1
    **Why** do you want to avoid loops? – Stefan Pochmann Oct 30 '17 at 11:46
  • @PRMoureu didn't really get your question but each dictionary stays at the same index once added to the list. – utengr Oct 30 '17 at 11:47
  • @StefanPochmann this piece of code is already inside loops so want to avoid a big nested loop. I can create a function for the check but was wondering if there will be another way to do it as a one-liner like a normal list membership check. – utengr Oct 30 '17 at 11:48

4 Answers4

2
any(d['item'] == redList for d in totalList)

Or with operator.itemgetter:

redList in map(itemgetter('item'), totalList)

Edit: Or just a generator expression (similar to Leandro's, but more space-efficient and perhaps more time-efficient as well, since it stops at the first finding):

redList in (d['item'] for d in totalList)
Stefan Pochmann
  • 24,379
  • 7
  • 36
  • 92
1

Try with this

if redList in [x.get('item') for x in totalList]:
    print("True")`
1

If you often need this check, it might be worth it to convert your lists to tuples. This way, they become hashable and can be saved in a set:

totalList = [{'score': 1, 'item': ['text1', 'text2']},
             {'score': 2, 'item': ['text3', 'text4']},
             {'score': 3, 'item': ['text5', 'text6']}]

items = {tuple(d['item']) for d in totalList}
print(items)
# {('text3', 'text4'), ('text1', 'text2'), ('text5', 'text6')}
redList = ['text1', 'text2']
print(tuple(redList) in items)
# True

You only need to iterate once in order to create the set. Every check will be fast and won't require any loop.

If you want to get the corresponding score, you could save the tuples in a dict:

scores = {tuple(d['item']):d['score'] for d in totalList}
print(scores)
# {('text1', 'text2'): 1, ('text3', 'text4'): 2, ('text5', 'text6'): 3}

print(scores.get(tuple(redList), 0))
# 1
print(scores.get(tuple(['a', 'b']), 0))
# 0
Eric Duminil
  • 48,038
  • 8
  • 56
  • 100
  • that's indeed a better solution, however, totalList keeps growing so its not a static list. Forgot to mention that in question. Just updated the question. Everytime the redlist is not in the totallist, I add a new dictionary to Totallist. – utengr Oct 30 '17 at 13:00
  • 1
    @utengr: No problem. `items` and `scores` are mutable. You can add new tuples any time you want. – Eric Duminil Oct 30 '17 at 13:06
  • you are right. I can add a new tuple to items every time I update totalList. – utengr Oct 30 '17 at 13:21
1

You can use filter:

redList = ['text1', 'text2']
totalList = ([{'score': 1, 'item': ['text1', 'text2']},
          {'score': 2, 'item': ['text3', 'text4']},
          {'score': 3, 'item': ['text5', 'text6']}])
if list(filter(lambda x:x["item"] == redList, totalList)):
    print('redList in totalList')
Ajax1234
  • 58,711
  • 7
  • 46
  • 83