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

Я сделал функцию, которая будет искать возраст в 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

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

for name, age in dictionary.items():    # for name, age in dictionary.iteritems():  (for Python 2.x)
    if age == search_age:
        print(name)

Ответ 2

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: Python: самый простой способ получить список значений из dict?

Ответ 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(list,search_age):
...     for name,age in list.iteritems():
...             if age == search_age:
...                     return name
... 
>>> def method2(list,search_age):
...     return [name for name,age in list.iteritems() if age == search_age]
... 
>>> def method3(list,search_age):
...     return list.keys()[list.values().index(search_age)]

Результаты из profile.run() по каждому методу 100000 раз:

Способ 1:

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

Способ 2:

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

Способ 3:

>>> profile.run("for i in range(0,100000): method3(list,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 ​​()) и сохраняет их в памяти.

Ответ 5

однострочная версия: (я старый словарь, р обратный словарь)

объяснение: i.keys() и i.values() возвращает два списка с ключами и значениями словаря соответственно. Функция zip имеет возможность связывать списки для создания словаря.

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

p = dict(zip(i.values(),i.keys()))

Ответ 6

a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]

или лучше

{k:v for k, v in a.items() if v == 1}

Ответ 7

lKey = [key for key, value in lDictionary.iteritems() if value == lValue][0]

Ответ 8

Вы можете получить ключ, используя dict.keys(), dict.values() и list.index(), см. Примеры кода ниже:

names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]

Ответ 9

Попробуйте эту однострочную, чтобы перевернуть словарь:

reversed_dictionary = dict(map(reversed, dictionary.items()))

Ответ 10

Вот мой вопрос по этой проблеме.:) Я только начал изучать Python, поэтому я называю это:

"Понятное для начинающих" решение.

#Code without comments.

list1 = {'george':16,'amber':19, 'Garry':19}
search_age = raw_input("Provide age: ")
print
search_age = int(search_age)

listByAge = {}

for name, age in list1.items():
    if age == search_age:
        age = str(age)
        results = name + " " +age
        print results

        age2 = int(age)
        listByAge[name] = listByAge.get(name,0)+age2

print
print listByAge

.

#Code with comments.
#I've added another name with the same age to the list.
list1 = {'george':16,'amber':19, 'Garry':19}
#Original code.
search_age = raw_input("Provide age: ")
print
#Because raw_input gives a string, we need to convert it to int,
#so we can search the dictionary list with it.
search_age = int(search_age)

#Here we define another empty dictionary, to store the results in a more 
#permanent way.
listByAge = {}

#We use double variable iteration, so we get both the name and age 
#on each run of the loop.
for name, age in list1.items():
    #Here we check if the User Defined age = the age parameter 
    #for this run of the loop.
    if age == search_age:
        #Here we convert Age back to string, because we will concatenate it 
        #with the person name. 
        age = str(age)
        #Here we concatenate.
        results = name + " " +age
        #If you want just the names and ages displayed you can delete
        #the code after "print results". If you want them stored, don't...
        print results

        #Here we create a second variable that uses the value of
        #the age for the current person in the list.
        #For example if "Anna" is "10", age2 = 10,
        #integer value which we can use in addition.
        age2 = int(age)
        #Here we use the method that checks or creates values in dictionaries.
        #We create a new entry for each name that matches the User Defined Age
        #with default value of 0, and then we add the value from age2.
        listByAge[name] = listByAge.get(name,0)+age2

#Here we print the new dictionary with the users with User Defined Age.
print
print listByAge

.

#Results
Running: *\test.py (Thu Jun 06 05:10:02 2013)

Provide age: 19

amber 19
Garry 19

{'amber': 19, 'Garry': 19}

Execution Successful!

Ответ 11

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

lookup = {value: key for key, value in self.data}
lookup[value]

Ответ 12

Я нашел этот ответ очень эффективным, но не очень легко читаемым для меня.

Чтобы сделать это более понятным, вы можете инвертировать ключ и значение словаря. Это сделать ключи значений и значения ключей, как показано здесь.

mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.iteritems())
print(res[16]) # Prints george

или же

mydict = {'george':16,'amber':19}
dict((v,k) for k,v in mydict.iteritems())[16]

что по сути то же самое, что этот другой ответ.

Ответ 13

Рассмотрим использование Pandas. Как указано в William McKinney "Python for Data Analysis"

Еще один способ подумать о серии - это фиксированная длина, упорядоченная dict, так как это отображение значений индекса в значения данных. Может быть используется во многих контекстах, где вы можете использовать dict.

import pandas as pd
list = {'george':16,'amber':19}
lookup_list = pd.Series(list)

Чтобы запросить свои ряды, выполните следующие действия:

lookup_list[lookup_list.values == 19]

Что дает:

Out[1]: 
amber    19
dtype: int64

Если вам нужно сделать что-нибудь еще с выходом, преобразующим ответ в список может быть полезен:

answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)

Ответ 14

Здесь функция recover_key использует словарь и значение для поиска в словаре. Затем мы перебираем ключи в словаре и сопоставляем их со значением и возвращаем этот конкретный ключ.

def recover_key(dicty,value):
    for a_key in dicty.keys():
        if (dicty[a_key] == value):
            return a_key

Ответ 15

get_key = lambda v, d: next(k for k in d if d[k] is v)

Ответ 16

for name in mydict.keys():
    if mydict[name] == search_age:
        print name 
        #or do something else with it. 
        #if in a function append to a temporary list, 
        #then after the loop return the list

Ответ 17

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

ages = {'george':16,'amber':19}
search = 16
print([name for (name, age) in ages.items() if age == search])

Ответ 18

он ответил, но это можно сделать с помощью фантастического использования "map/reduce", например:

def find_key(value, dictionary):
    return reduce(lambda x, y: x if x is not None else y,
                  map(lambda x: x[0] if x[1] == value else None, 
                      dictionary.iteritems()))

Ответ 19

вот мое занятие. Это полезно для отображения нескольких результатов на случай, если вам это нужно. Поэтому я также добавил список

myList = {'george':16,'amber':19, 'rachel':19, 
           'david':15 }                         #Setting the dictionary
result=[]                                       #Making ready of the result list
search_age = int(input('Enter age '))

for keywords in myList.keys():
    if myList[keywords] ==search_age:
    result.append(keywords)                    #This part, we are making list of results

for res in result:                             #We are now printing the results
    print(res)

И что это...

Ответ 20

Нет простого способа найти ключ в списке, "посмотрев" значение. Однако, если вы знаете значение, итерации через клавиши, вы можете искать значения в словаре элементом. Если D [элемент], где D - объект словаря, равен ключу, который вы пытаетесь найти, вы можете выполнить некоторый код.

D = {'Ali': 20, 'Marina': 12, 'George':16}
age = int(input('enter age:\t'))  
for element in D.keys():
    if D[element] == age:
        print(element)

Ответ 21

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

Ответ 22

мы можем получить Key от dict по:

def getKey(dict,value):
     return [key for key in dict.keys() if (dict[key] == value)]

Ответ 23

Cat Plus Plus упомянул, что это не значит, что словарь предназначен для использования. Вот почему:

Определение словаря аналогично определению в математике. В этом случае dict - это отображение K (набор ключей) в V (значения), но не наоборот. Если вы разыскиваете диктофон, вы ожидаете получить ровно одно возвращаемое значение. Но для разных ключей вполне возможно сопоставить одно значение, например:

d = { k1 : v1, k2 : v2, k3 : v1}

Когда вы подбираете ключ по соответствующему значению, вы, по сути, инвертируете словарь. Но отображение не обязательно обратимо! В этом примере запрос ключа, соответствующего v1, может дать k1 ​​или k3. Если вы вернете оба? Только первый найден? Вот почему indexof() undefined для словарей.

Если вы знаете свои данные, вы можете это сделать. Но API не может предположить, что произвольный словарь обратим, следовательно, отсутствие такой операции.

Ответ 24

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

dict((v,k) for k,v in d.items()).get(16)

Выход выглядит следующим образом:

-> prints george

Ответ 25

Вам нужно использовать словарь и обратный словарь. Это означает, что вам нужна другая структура данных. Если вы находитесь в python 3, используйте модуль enum, но если вы используете python 2.7, используйте enum34, который портирован для python 2.

Пример:

from enum import Enum

class Color(Enum): 
    red = 1 
    green = 2 
    blue = 3

>>> print(Color.red) 
Color.red

>>> print(repr(Color.red)) 
<color.red: 1=""> 

>>> type(Color.red) 
<enum 'color'=""> 
>>> isinstance(Color.green, Color) 
True 

>>> member = Color.red 
>>> member.name 
'red' 
>>> member.value 
1 

Ответ 26

Надеюсь, это поможет...

for key in list:
   if list[key] == search_value:
       return key

Ответ 27

уже был дан ответ, но, поскольку несколько человек упомянули обратный словарь, вот как вы это делаете в одной строке (при условии отображения 1:1) и некоторых различных первичных данных:

python 2.6:

reversedict = dict([(value, key) for key, value in mydict.iteritems()])

2,7 +

reversedict = {value:key for key, value in mydict.iteritems()}

если вы думаете, что это не 1:1, вы все равно можете создать разумное обратное отображение с двумя строками:

reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]

насколько медленным является это: медленнее, чем простой поиск, но не так медленно, как вы думаете, - в "прямом" словарях из 100 000 слов "быстрый" поиск (т.е. поиск значения, которое должно быть на раннем этапе ключи) было примерно в 10 раз быстрее, чем вспять весь словарь, а "медленный" поиск (ближе к концу) примерно на 4-5 раз быстрее. Таким образом, после почти десяти поисков он заплатил за себя.

вторая версия (со списками для каждого элемента) занимает около 2,5x, если простая версия.

largedict = dict((x,x) for x in range(100000))

# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop

# Should be fast, has to only search 9 entries to find it. 
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop

# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.

In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop

In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop

In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop

In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop

Также были интересные результаты с ifilter. Теоретически, ifilter должен быть быстрее, поскольку мы можем использовать itervalues ​​() и, возможно, вам не нужно создавать/просматривать список всех значений. На практике результаты были... нечетными...

In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop

In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop

Таким образом, для небольших смещений это было значительно быстрее, чем любая предыдущая версия (2.36 * u * S против минимума 1,48 * м * S для предыдущих случаев). Однако для больших смещений ближе к концу списка это было значительно медленнее (15,1 мс против тех же 1,48 мс). Небольшая экономия на низком уровне не стоит затрат на высоком уровне, imho.

Ответ 28

Иногда может потребоваться int():

titleDic = {'Фильмы':1, 'Музыка':2}

def categoryTitleForNumber(self, num):
    search_title = ''
    for title, titleNum in self.titleDic.items():
        if int(titleNum) == int(num):
            search_title = title
    return search_title

Ответ 29

Вот как вы получаете доступ к словарю, чтобы делать то, что вы хотите:

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

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

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

Еще лучше:

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

Ответ 30

dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
key = [filter( lambda x: dictionary[x] == k  , dictionary ),[None]][0] 
# key = None from [None] which is a safeguard for not found.

Для нескольких случаев используйте:

keys = [filter( lambda x: dictionary[x] == k  , dictionary )]