Вопрос-Ответ

Get key by value in dictionary

Получение ключа по значению в словаре

Я создал функцию, которая будет искать возраст в Dictionary и показывать соответствующее имя:

dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
if age == search_age:
name = dictionary[age]
print name

Я знаю, как сравнить и найти возраст, я просто не знаю, как показать имя человека. Кроме того, я получаю KeyError из-за строки 5. Я знаю, что это неправильно, но я не могу понять, как заставить его выполнять поиск в обратном направлении.

Переведено автоматически
Ответ 1
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)] # Prints george

Или в Python 3.x:

mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)]) # Prints george

По сути, он разделяет значения словаря в списке, находит позицию имеющегося у вас значения и получает ключ в этой позиции.

Подробнее о keys() и .values() в Python 3: Как я могу получить список значений из dict?

Ответ 2

Такого нет. dict не предназначен для использования таким образом.

dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items(): # for name, age in dictionary.iteritems(): (for Python 2.x)
if age == search_age:
print(name)
Ответ 3

Если вам нужны и имя, и возраст, вы должны использовать .items() который предоставляет вам кортежи ключей (key, value):

for name, age in mydict.items():
if age == search_age:
print name

Вы можете распаковать кортеж в две отдельные переменные прямо в for цикле, затем сопоставить возраст.

Вам также следует рассмотреть возможность изменения словаря местами, если вы обычно собираетесь искать по возрасту, и нет двух людей одинакового возраста:

{16: 'george', 19: 'amber'}

итак, вы можете найти имя для возраста, просто выполнив

mydict[search_age]

Я называл это mydict вместо list потому что list это имя встроенного типа, и вы не должны использовать это имя для чего-либо еще.

Вы даже можете получить список всех людей с заданным возрастом в одной строке:

[name for name, age in mydict.items() if age == search_age]

или если есть только один человек с каждым возрастом:

next((name for name, age in mydict.items() if age == search_age), None)

который просто выдаст вам None, если нет никого с таким возрастом.

Наконец, если dict длинный и вы используете Python 2, вам следует рассмотреть возможность использования .iteritems() вместо .items(), как это сделал Cat Plus Plus в своем ответе, поскольку ему не нужно создавать копию списка.

Ответ 4

Я подумал, что было бы интересно указать, какие методы являются самыми быстрыми и в каком сценарии:

Вот несколько тестов, которые я провел (на MacBook Pro 2012 года выпуска)

def method1(dict, search_age):
for name, age in dict.iteritems():
if age == search_age:
return name

def method2(dict, search_age):
return [name for name,age in dict.iteritems() if age == search_age]

def method3(dict, search_age):
return dict.keys()[dict.values().index(search_age)]

Результат profile.run() для каждого метода 100 000 раз:

Метод 1:

>>> profile.run("for i in range(0,100000): method1(dict, 16)")
200004 function calls in 1.173 seconds

Метод 2:

>>> profile.run("for i in range(0,100000): method2(dict, 16)")
200004 function calls in 1.222 seconds

Метод 3:

>>> profile.run("for i in range(0,100000): method3(dict, 16)")
400004 function calls in 2.125 seconds

Итак, это показывает, что для небольшого dict метод 1 является самым быстрым. Это, скорее всего, потому, что он возвращает первое совпадение, в отличие от всех совпадений, подобных методу 2 (см. Примечание ниже).


Интересно, что, выполняя те же тесты для dict, которые у меня есть с 2700 записями, я получаю совершенно другие результаты (на этот раз выполняю 10000 раз):

Метод 1:

>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
20004 function calls in 2.928 seconds

Метод 2:

>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
20004 function calls in 3.872 seconds

Метод 3:

>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
40004 function calls in 1.176 seconds

Итак, здесь метод 3 намного быстрее. Просто хочу показать, что размер вашего dict повлияет на то, какой метод вы выберете.

Примечания:


  • Метод 2 возвращает список всех имен, тогда как методы 1 и 3 возвращают только первое совпадение.

  • Я не учитывал использование памяти. Я не уверен, создает ли метод 3 2 дополнительных списка (keys() и values()) и сохраняет ли их в памяти.

python dictionary