15

What would be the Pythonic way to check if ANY element in a list is a key in a dictionary?

Example, I have a list of fruits:

fruits = ['apples', 'bananas', 'pears']

And want to check if ANY fruit is a key in my dictionary, examples:

fruit_dict1 = {'apples': 4, 'oranges': 3, 'dragonfruit': 4} returns True

fruit_dict2 = {'oranges': 3, 'dragonfruit': 9, 'pineapples': 4} returns False

So far I have:

def fruit_checker(list, dict):
    for fruit in list:
        if fruit in dict:
            return True
    return False

It feels weird to just look for a fruit "in" a dictionary, but it seems "in" only does a search on dictionary keys. How exactly does "in" work with the different types?

devonj
  • 1,198
  • 1
  • 13
  • 24
  • Why does it feel weird to use `in` with dictionaries if it does exactly what you wish? – DeepSpace Jul 07 '16 at 06:40
  • 1
    To answer your question: see https://docs.python.org/2/reference/datamodel.html#object.__contains__. Briefly, if your object defines `__contains__`, `__iter__`, or `__getitem__`, then `in` operator should work. It is up to the implementation to do something sensible. For `dict`, `__contains__` returns True if the value passed is in the keys. – Alok Singhal Jul 07 '16 at 06:44
  • The keys of the dictionary are a sequence; all the same techniques in the linked duplicate apply. – Karl Knechtel Aug 02 '22 at 23:58

4 Answers4

18

Try this

In [1]: any([i in fruit_dict1 for i in fruits])
Out[1]: True
In [2]: any([i in fruit_dict2 for i in fruits])
Out[2]: False

Working

In [11]: [i in fruit_dict2 for i in fruits]
Out[11]: [False, False, False]

Which check the every element present. And return a list of boolean values and any will return if any True is exist.

In [13]: any([True,False,False])
Out[13]: True
Rahul K P
  • 15,740
  • 4
  • 35
  • 52
  • 1
    In your first solution you don't need to create the extra lists. You can `any(fruit in fruit_dict for i in fruits)`. You also don't need `keys()`, the `in` operator does that by default. With the list comprehension and `keys()` you are creating 2 extra lists. Trivial here, but could be costly in other situations. – kylieCatt Jul 07 '16 at 07:01
  • @RahulKP, IanAuld is right, please accept my edits without the keys() method and I will make this the accepted answer – devonj Jul 07 '16 at 19:32
  • @devonJS Updated my answer. – Rahul K P Jul 08 '16 at 04:59
7

Let's define your variables:

>>> fruits = ['apples', 'bananas', 'pears']
>>> fruit_dict1 = {'apples': 4, 'oranges': 3, 'dragonfruit': 4}
>>> fruit_dict2 = {'oranges': 3, 'dragonfruit': 9, 'pineapples': 4}

Now, let's test for membership:

>>> bool(set(fruits).intersection(fruit_dict1))
True
>>> bool(set(fruits).intersection(fruit_dict2))
False

How it works

set(fruits) is the set of fruits. We want to find if there is any overlap between this set and the set of keys of your dictionaries. To find what the overlap is, we can use the intersection method:

>>> set(fruits).intersection(fruit_dict1)
set(['apples'])

To convert this to True for a non-empty intersection or False for an empty one, we use bool:

>>> bool(set(fruits).intersection(fruit_dict1))
True

Minor variation

The same principles if we reverse the order:

>>> bool(set(fruit_dict1).intersection(fruits))
True
>>> bool(set(fruit_dict2).intersection(fruits))
False
John1024
  • 109,961
  • 14
  • 137
  • 171
4

Pass a generator that iterates over the list to any:

fruits = ['apples', 'bananas', 'pears']
fruit_dict1 = {'apples': 4, 'oranges': 3, 'dragonfruit': 4}

print(any(list_item in fruit_dict1 for list_item in fruits))
>> True

fruit_dict2 = {'oranges': 3, 'dragonfruit': 9, 'pineapples': 4}

print(any(list_item in fruit_dict2 for list_item in fruits))
>> False
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
2
set(fruits) & set(fruit_dict1.keys())

or using Counter

from collections import Counter
any(Counter(fruits) & Counter(fruit_dict1.keys()))
SuperNova
  • 25,512
  • 7
  • 93
  • 64