Mayank Srivastava
Mayank Srivastava

Reputation: 159

How to get all keys from a value for a dict of lists?

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

Answers (5)

Niladri Basu
Niladri Basu

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

Jean-François Fabre
Jean-François Fabre

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

Rahul K P
Rahul K P

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

jpp
jpp

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

timgeb
timgeb

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

Related Questions