There is a dictionary, the values ​​in it are lists of elements:

d = {'Люди': ['Ваня', 'Маша', 'Петя'], 'Кони': ['Горбунок', 'Буцефал']} 

Is there a way to get a key from the dictionary if one of the list items is known?

 Ваня - Люди, Буцефал - Кони, Чубакка - None 

    3 answers 3

    It depends on the size of the dictionary. If we are talking about 10 4 elements and less, then you can simply build a reverse dictionary:

     In [1]: d = {'Люди': ['Ваня', 'Маша', 'Петя'], 'Кони': ['Горбунок', 'Буцефал']} In [2]: from collections import defaultdict In [3]: d1 = defaultdict(list) In [4]: for k, vs in d.items(): ...: for v in vs: ...: d1[v].append(k) ...: In [5]: d1 Out[5]: defaultdict(list, {'Буцефал': ['Кони'], 'Ваня': ['Люди'], 'Горбунок': ['Кони'], 'Маша': ['Люди'], 'Петя': ['Люди']}) In [6]: '; '.join(x + ' - ' + ', '.join(map(str, d1.get(x, [None]))) for x in ['Ваня', 'Буцефал', 'Чубакка']) Out[6]: 'Ваня - Люди; Буцефал - Кони; Чубакка - None' 

    If the number of elements is large enough, it makes sense to think about the implementation of a bidirectional dictionary.

      Build a reverse dictionary:

       d = {'Люди': ['Ваня', 'Маша', 'Петя'], 'Кони': ['Горбунок', 'Буцефал']} rev_d = dict((v, k) for k, vals in d.items() for v in vals) # Проверяем print(rev_d.get('Ваня')) print(rev_d.get('Буцефал')) print(rev_d.get('Чубакка') 
      • one
        The list should be used as in the answer @soon , if the initial value can occur in several lists (correspond to several keys). - jfs
      • Yes, if the lists of values ​​overlap, then you should use the @soon solution. If not, as in the original request, then the one presented is a bit more compact. :) - tonal
       d = {'Люди': ['Ваня', 'Маша', 'Петя', '1'], 'Кони': ['Горбунок', 'Буцефал', '1']} def find_me(name): return [k for k in d if set(d[k]) & {name}] print('Ваня :', find_me('Ваня')) print('1 :', find_me('1')) 

      Conclusion:

       Ваня : ['Люди'] 1 : ['Люди', 'Кони'] 
      • It makes no sense to create a temporary set — name in d[k] works as it is: return [key for key, lst in d.items() if name in lst] . Although if you want to find several names, it makes sense to create a reverse dictionary as in the answer @soon . - jfs