Use of builtin any can have some performance edge over two loops
any(x in someDict for x in someList)
but you might need to measure your mileage. If your list and dict remains pretty static and you have to perform the comparison multiple times, you may consider using set
someSet = set(someList)
someDict.viewkeys() & someSet
Note Python 3.X, by default returns views rather than a sequence, so it would be straight forward when using Python 3.X
someSet = set(someList)
someDict.keys() & someSet
In both the above cases you can wrap the result with a bool to get a boolean result
bool(someDict.keys() & set(someSet ))
Heretic Note
My curiosity took better of me and I timed all the proposed solutions. It seems, your original solution is better performance wise. Here is the result
Sample Randomly generated Input
>>> import timeit
>>> import random
>>> some_list = random.sample(range(1,10000),10)
>>> some_dict = dict(zip(random.sample(range(1,10000),10), random.sample(range(1,10000),10)))
Test Result
>>> def foo_set(some_list, some_dict):
return some_dict.viewkeys() & set(some_list )
>>> def foo_nested(some_list, some_dict):
for x in some_list:
if x in some_dict:
return True
return False
>>> def foo_any(some_list, some_dict):
return any(x in some_dict for x in some_list)
>>> def foo_ifilter(some_list, some_dict):
return bool(next(ifilter(some_dict.__contains__, some_list), False))
>>> def foo_ifilter_new(some_list, some_dict):
return not not next(ifilter(someDict.__contains__, someList), False)
>>> def foo_ifilter_v3(some_list, some_dict):
return any(ifilter(some_dict.__contains__, some_list))
>>> # Timeit wrapper
>>> def time(fn):
return timeit.timeit("{}(some_list, some_dict)".format(fn),
setup="from __main__ import {}, ifilter, some_list, some_dict".format(fn))
>>> time("foo_nested")
1.054499578614525
>>> time("foo_ifilter")
1.2866317889381662
>>> time("foo_any")
1.4705059825669196
>>> time("foo_set")
5.068478196019896
>>> time("foo_ifilter")
1.268290360447736
>>> time("foo_ifilter_v3")
1.070190605300013
I understand, that the solution utilizing set is not a good use case here, so I retested it without recreating the set on each iteration
>>> def foo_set(some_list, some_dict):
return some_dict.viewkeys() & some_set
>>> some_set = set(some_list)
>>> print timeit.timeit("foo_set(some_list, some_dict)",
setup="from __main__ import foo_set, ifilter, some_list, some_dict")
2.72747207852
I also tested what Ashwin suggested and there is a 2 fold increase in performance.
>>> def foo_set(some_list, some_dict):
return not set(some_dict).isdisjoint(some_list)
>>> time("foo_set")
2.357448644513852
Summarizing the result
╔══════════════════════════════════╦══════╦════════════════════╗
║ Procedure ║ Rank ║ Result ║
╠══════════════════════════════════╬══════╬════════════════════╣
║ Nested Loop ║ 1 ║ 1.054499578614525 ║
║ ifilter/all (edited) ║ 2 ║ 1.070190605300013 ║
║ ifilter/next (suggested) ║ 3 ║ 1.268290360447736 ║
║ ifilter/next ║ 4 ║ 1.2866317889381662 ║
║ any ║ 5 ║ 1.4705059825669196 ║
║ set (without dict views ) ║ 6 ║ 2.357448644513852 ║
║ set (optimized for dynamic data) ║ 7 ║ 2.72747207852 ║
║ set ║ 8 ║ 5.068478196019896 ║
╚══════════════════════════════════╩══════╩════════════════════╝