効率的な解決策として、明示的なループをできるだけ避けたいと考えています。
items = set(items)
fruits = set(foods_dict['fruit']) & items
veggies = set(foods_dict['veg']) & items
others = items - fruits - veggies
これは、明示的なループを使用するよりも確実に高速です。特にitem in foods_dict['fruit']
、果物のリストが長い場合、実行に時間がかかります。
これまでのソリューション間の非常に単純なベンチマーク:
In [5]: %%timeit
...: items2 = set(items)
...: fruits = set(foods_dict['fruit']) & items2
...: veggies = set(foods_dict['veg']) & items2
...: others = items2 - fruits - veggies
...:
1000000 loops, best of 3: 1.75 us per loop
In [6]: %%timeit
...: fruits = set()
...: veggies = set()
...: others = set()
...: for item in items:
...: if item in foods_dict.get('fruit'):
...: fruits.add(item)
...: elif item in foods_dict.get('veg'):
...: veggies.add(item)
...: else:
...: others.add(item)
...:
100000 loops, best of 3: 2.57 us per loop
In [7]: %%timeit
...: veggies = set(elem for elem in items if elem in foods_dict['veg'])
...: fruits = set(elem for elem in items if elem in foods_dict['fruit'])
...: others = set(items) - veggies - fruits
...:
100000 loops, best of 3: 3.34 us per loop
確かに、選択する前に、「実際の入力」でいくつかのテストを行う必要があります。問題に含まれる要素の数についてはわかりません。入力が大きくなると、タイミングが大きく変わる可能性があります。とにかく、私の経験から、少なくとも CPython では、明示的なループは組み込み操作のみを使用するよりも遅くなる傾向があることがわかります。
Edit2:より大きな入力の例:
In [9]: foods_dict = {}
...: foods_dict['fruit'] = list(range(0, 10000, 2))
...: foods_dict['veg'] = list(range(1, 10000, 2))
In [10]: items = list(range(5, 10000, 13)) #some odd some even
In [11]: %%timeit
...: fruits = set()
...: veggies = set()
...: others = set()
...: for item in items:
...: if item in foods_dict.get('fruit'):
...: fruits.add(item)
...: elif item in foods_dict.get('veg'):
...: veggies.add(item)
...: else:
...: others.add(item)
...:
10 loops, best of 3: 68.8 ms per loop
In [12]: %%timeit
...: veggies = set(elem for elem in items if elem in foods_dict['veg'])
...: fruits = set(elem for elem in items if elem in foods_dict['fruit'])
...: others = set(items) - veggies - fruits
...:
10 loops, best of 3: 99.9 ms per loop
In [13]: %%timeit
...: items2 = set(items)
...: fruits = set(foods_dict['fruit']) & items2
...: veggies = set(foods_dict['veg']) & items2
...: others = items2 - fruits - veggies
...:
1000 loops, best of 3: 445 us per loop
ご覧のとおり、組み込みのみを使用すると、明示的なループよりも約 20 倍速くなります。