Ответ 1
Здесь ничего нет. dict
не предназначен для использования таким образом.
for name, age in dictionary.items(): # for name, age in dictionary.iteritems(): (for Python 2.x)
if age == search_age:
print(name)
Я сделал функцию, которая будет искать возраст в 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. Я знаю, что это не правильно, но я не могу понять, как заставить его искать в обратном направлении.
Здесь ничего нет. dict
не предназначен для использования таким образом.
for name, age in dictionary.items(): # for name, age in dictionary.iteritems(): (for Python 2.x)
if age == search_age:
print(name)
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?
Если вы хотите как имя, так и возраст, вы должны использовать .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 в своем ответе, поскольку ему не нужно делать копия списка.
Я подумал, что было бы интересно указать, какие методы самые быстрые, и в каком сценарии:
Вот некоторые тесты, которые я провел (на 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 ()) и сохраняет их в памяти.
однострочная версия: (я старый словарь, р обратный словарь)
объяснение: i.keys() и i.values() возвращает два списка с ключами и значениями словаря соответственно. Функция zip имеет возможность связывать списки для создания словаря.
предупреждение: это будет работать, только если значения являются хэшируемыми и уникальными.
p = dict(zip(i.values(),i.keys()))
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}
lKey = [key for key, value in lDictionary.iteritems() if value == lValue][0]
Вы можете получить ключ, используя 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)]
Попробуйте эту однострочную, чтобы перевернуть словарь:
reversed_dictionary = dict(map(reversed, dictionary.items()))
Вот мой вопрос по этой проблеме.:) Я только начал изучать 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!
Если вы хотите найти ключ по значению, вы можете использовать понимание словаря для создания словаря поиска, а затем использовать его для поиска ключа из значения.
lookup = {value: key for key, value in self.data}
lookup[value]
Я нашел этот ответ очень эффективным, но не очень легко читаемым для меня.
Чтобы сделать это более понятным, вы можете инвертировать ключ и значение словаря. Это сделать ключи значений и значения ключей, как показано здесь.
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]
что по сути то же самое, что этот другой ответ.
Рассмотрим использование 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)
Здесь функция recover_key использует словарь и значение для поиска в словаре. Затем мы перебираем ключи в словаре и сопоставляем их со значением и возвращаем этот конкретный ключ.
def recover_key(dicty,value):
for a_key in dicty.keys():
if (dicty[a_key] == value):
return a_key
get_key = lambda v, d: next(k for k in d if d[k] is v)
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
Я знаю, что это устарело, но вы можете легко найти всех людей в списке с возрастом поиска, используя понимание списка.
ages = {'george':16,'amber':19}
search = 16
print([name for (name, age) in ages.items() if age == search])
он ответил, но это можно сделать с помощью фантастического использования "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()))
вот мое занятие. Это полезно для отображения нескольких результатов на случай, если вам это нужно. Поэтому я также добавил список
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)
И что это...
Нет простого способа найти ключ в списке, "посмотрев" значение. Однако, если вы знаете значение, итерации через клавиши, вы можете искать значения в словаре элементом. Если 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)
def get_Value(dic,value):
for name in dic:
if dic[name] == value:
del dic[name]
return name
мы можем получить Key
от dict
по:
def getKey(dict,value):
return [key for key in dict.keys() if (dict[key] == value)]
Cat Plus Plus упомянул, что это не значит, что словарь предназначен для использования. Вот почему:
Определение словаря аналогично определению в математике. В этом случае dict - это отображение K (набор ключей) в V (значения), но не наоборот. Если вы разыскиваете диктофон, вы ожидаете получить ровно одно возвращаемое значение. Но для разных ключей вполне возможно сопоставить одно значение, например:
d = { k1 : v1, k2 : v2, k3 : v1}
Когда вы подбираете ключ по соответствующему значению, вы, по сути, инвертируете словарь. Но отображение не обязательно обратимо! В этом примере запрос ключа, соответствующего v1, может дать k1 или k3. Если вы вернете оба? Только первый найден? Вот почему indexof() undefined для словарей.
Если вы знаете свои данные, вы можете это сделать. Но API не может предположить, что произвольный словарь обратим, следовательно, отсутствие такой операции.
d= {'george':16,'amber':19}
dict((v,k) for k,v in d.items()).get(16)
Выход выглядит следующим образом:
-> prints george
Вам нужно использовать словарь и обратный словарь. Это означает, что вам нужна другая структура данных. Если вы находитесь в 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
Надеюсь, это поможет...
for key in list:
if list[key] == search_value:
return key
уже был дан ответ, но, поскольку несколько человек упомянули обратный словарь, вот как вы это делаете в одной строке (при условии отображения 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.
Иногда может потребоваться 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
Вот как вы получаете доступ к словарю, чтобы делать то, что вы хотите:
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
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 )]