Reputation: 159
I have a dictionary in a format like this
d = {
"Fruit_1" : ["mango", "apple"],
"Fruit_2" : ["apple"],
"Fruit_3" : ["mango", "banana", "apple", "kiwi", "orange"]
}
I'm passing a value as "mango" and I want to get all corresponding keys where only mango occurs. I am not able to get corresponding keys where ever value occurs.
Upvotes: 3
Views: 10524
Reputation: 10624
You can do this perhaps:
d = {
"Fruit_1" : ["mango", "apple"],
"Fruit_2" : ["apple"],
"Fruit_3" : ["mango", "banana", "apple", "kiwi", "orange"]
}
# list comprehension
mango_keys = [fruit for fruit in d.keys() if "mango" in d[fruit]]
print(mango_keys)
# ['Fruit_1', 'Fruit_3']
# or more traditional for-loop (but non pythonic)
for fruit in d.keys():
if "mango" in d[fruit]:
print(fruit)
Upvotes: 2
Reputation: 140287
The naive approaches (looping through all items and looking for the fruit) work but have a high complexity, mostly if you have to perform a lot of requests. You could slightly improve it by replacing your list
values by a set
(for faster in
lookup), but that would still be slow (O(n**2)
=> O(n)
but room for improvement).
If you want to be able to perform those queries a lot of times, it would be better to rebuild the dictionary so lookup is very fast once built, using collections.defaultdict
d = {
"Fruit_1" : ["mango", "apple"],
"Fruit_2" : ["apple"],
"Fruit_3" : ["mango", "banana", "apple", "kiwi", "orange"]
}
import collections
newd = collections.defaultdict(list)
for k,vl in d.items():
for v in vl:
newd[v].append(k)
print(newd)
print(newd["mango"])
this is the rebuilt dict:
defaultdict(<class 'list'>, {'apple': ['Fruit_2', 'Fruit_3', 'Fruit_1'], 'orange': ['Fruit_3'], 'banana': ['Fruit_3'], 'kiwi': ['Fruit_3'], 'mango': ['Fruit_3', 'Fruit_1']})
this is the query for "mango":
['Fruit_3', 'Fruit_1']
Upvotes: 2
Reputation: 16081
Iterate in d.items
and check mango
existence in value.
In [21]: [key for key,value in d.items() if 'mango' in value]
Out[21]: ['Fruit_1', 'Fruit_3']
Upvotes: 9
Reputation: 164823
For a single query, you can use a list comprehension. This will has O(n) time complexity each time you search a value:
res = [k for k, v in d.items() if 'mango' in v]
For multiple queries, you can use a defaultdict
of set
objects via a one-off O(n) cost:
from collections import defaultdict
dd = defaultdict(set)
for k, v in d.items():
for fruit in v:
dd[fruit].add(k)
print(dd)
defaultdict({'mango': {'Fruit_1', 'Fruit_3'},
'apple': {'Fruit_1', 'Fruit_2', 'Fruit_3'},
'banana': {'Fruit_3'},
'kiwi': {'Fruit_3'},
'orange': {'Fruit_3'}})
You can then use dd['mango']
to extract relevant keys.
Upvotes: 1
Reputation: 78780
Like this?
>>> d = {
... "Fruit_1" : ["mango", "apple"],
... "Fruit_2" : ["apple"],
... "Fruit_3" : ["mango", "banana", "apple", "kiwi", "orange"]
... }
>>>
>>> [key for key, value in d.items() if 'mango' in value]
['Fruit_1', 'Fruit_3']
The idea is to iterate over the (key, value) itempairs and check each value for the existence of 'mango'
. If yes, keep the key.
Since you are new to Python here's the tradidtional for
-loop logic:
>>> result = []
>>> for key, value in d.items():
... if 'mango' in value:
... result.append(key)
...
>>> result
['Fruit_1', 'Fruit_3']
Upvotes: 1