получить ключ по значению, dict, python

Как я могу получить ключ от значения?

мой дикт:

countries = { "Normal UK project" : "1", "UK Omnibus project" : "1-Omni", "Nordic project" : ["11","12","13","14"], "German project" : "21", "French project" : "31" } 

мой полуфункциональный код:

 for k, v in countries.items(): if "1" in v: print k 

ожидаемый результат:

 Normal UK project 

фактический результат:

 French project UK Omnibus project German project Normal UK project 

Как я могу исправить свой код?

    Проблема в том, что типы значений в словаре не совпадают, что затрудняет использование словаря не только в этом сценарии. Хотя Python позволяет это, вам действительно следует рассмотреть возможность объединения типов в словаре, например, сделать их всеми списками. Вы можете сделать это только в одной строке кода:

     countries = {key: val if isinstance(val, list) else [val] for key, val in countries.items()} 

    Теперь каждая отдельная строка завернута в список, и ваш существующий код будет работать правильно.

    В качестве альтернативы, если вам нужно использовать словарь в текущей форме, вы можете настроить функцию поиска:

     for k, v in countries.items(): if "1" == v or isinstance(v, list) and "1" in v: print k 

    c={} – любой dict
    a (значение) – нужно знать этот ключ

     key=list(c.keys())[list(c.values()).index(a)]] 
     def keys_of_value(dct, value): for k in dct: if isinstance(dct[k], list): if value in dct[k]: return k else: if value == dct[k]: return k assert keys_of_value(countries, "12") == "Nordic project" assert keys_of_value(countries, "1") == "Normal UK project" 

    Если вы хотите, чтобы я немного сократил его, я мог бы сделать

     from operator import eq, contains def keys_of_value(dct, value, ops = (eq, contains)): for k in dct: if ops[isinstance(dct[k], list)](dct[k], value): return k assert keys_of_value(countries, "12") == "Nordic project" assert keys_of_value(countries, "1") == "Normal UK project" 

    Ваш полуфункциональный код возвращает другие значения, потому что такие записи, как:

      "Normal UK project" : "1", 

    .. then "1" in v проверяет, содержит ли строка символ «1», тогда как записи:

      "Nordic project" : ["11","12","13","14"], 

    Затем будет проверяться, содержит ли список элемент «1».

    Оператор in работает как по строкам, так и по спискам, но по-другому:

     >>> "1" in "123" True >>> "1" in ["123", "blah"] False >>> "1" in ["1", "blah"] True 

    В идеале ваши данные будут более согласованными – все списки или все строки:

     countries = { "Normal UK project" : ["1"], "UK Omnibus project" : ["1-Omni"], "Nordic project" : ["11","12","13","14"], "German project" : ["21"], "French project" : ["31"] } for k, v in countries.items(): if "1" in v: print k 

    Я лично считаю, что использование values in и функций намного проще.

     print 1 in {1:"123", 2:"blah"} print "blah" in {1:"123", 2:"blah"}.values() 

    Выход:

     True True 
     def get_Value(dic,value): for name in dic: if dic[name] == value: return name 

    Следующий код предоставляет другую и короткую версию получения ключей словарями с помощью некоторого значения, используя списки и dic.items ():

     keys_have_value = [k for k,v in dic.items() if v=="1"]