在字典中按值获取密钥

use*_*316 575 python dictionary

我创建了一个函数,它将在a中查找年龄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
Run Code Online (Sandbox Code Playgroud)

我知道如何比较和找到我只是不知道如何显示这个人的名字的年龄.另外,KeyError由于第5行,我得到了一个.我知道这不正确,但我无法弄清楚如何让它向后搜索.

小智 530

mydict = {'george':16,'amber':19}
print mydict.keys()[mydict.values().index(16)] # Prints george
Run Code Online (Sandbox Code Playgroud)

或者在Python 3.x中:

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

基本上,它将列表中的字典值分开,找到您拥有的值的位置,并获取该位置的键.

更多关于keys().values()在Python 3:Python的:最简单的方式来获得字典的值列表?

  • 看起来很棒,但总是有效吗?我的意思是,`list.keys()`和`list.values()`函数是否以相同的顺序生成项目? (20认同)
  • 是的,它们保证一致.此外,只要未修改字典,保证顺序不会通过迭代进行更改. (13认同)
  • @ArtOfWarfare https://docs.python.org/3/library/stdtypes.html#dict-views,"如果重复键,值和项目视图而不对字典进行干预修改,则项目的顺序将直接对应". (10认同)
  • 这看起来是一个很好的解决方案,但索引只给了一个值,所以如果你有多个相等的值,那么它应该返回多个键吗? (8认同)
  • @sinekonata:它仍然在引擎盖下执行昂贵的循环; 循环只是隐藏在`index`方法中. (5认同)
  • 在我知道只有一个键可能有问题的情况下,这个解决方案很适合我,但是,如果存在多个值,它将返回其中一个.(P 2.6) (3认同)
  • list(mydict) 与 list(mydict.keys()) 做同样的事情 (2认同)

Cat*_*lus 509

空无一人.dict不打算以这种方式使用.

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

  • 在`Python 3.x`中,list.items()`应该使用`而不是`list.iteritems()` (123认同)
  • 我不同意......下面的agf答案更有建设性.一个完全合理的用例不是"无意的"(列表理解无论如何都适合这样的用例).`dict`可以在不同的时间用于多种事物; 当然,键和值具有明确的含义,但_"`dict`项具有给定值"_是一个非常合理的请求.使用对列表的建议会丢弃一个项目是另一个项目的'_definition_'的上下文,例如在参数列表中... (50认同)
  • 我不同意这个答案。事实上,正如 Stênio Elson 的回答所示,这是一种可能性,并不意味着它不打算这样使用。一点帮助都没有。 (6认同)
  • @JossieCalderon 是的。我经常用谷歌搜索我的意思的描述来得到这个词。这本质上是根据定义在字典中查找单词。 (6认同)

agf*_*agf 237

如果你想要名字年龄,你应该使用.items()哪个给你关键(key, value)元组:

for name, age in mydict.items():
    if age == search_age:
        print name
Run Code Online (Sandbox Code Playgroud)

您可以在for循环中将元组解压缩为两个单独的变量,然后匹配年龄.

如果你通常会按年龄查看,你也应该考虑撤销字典,而且没有两个人有相同的年龄:

{16: 'george', 19: 'amber'}
Run Code Online (Sandbox Code Playgroud)

所以你可以通过这样做来查找年龄的名称

mydict[search_age]
Run Code Online (Sandbox Code Playgroud)

我一直在调用它,mydict而不是list因为它list是内置类型的名称,你不应该使用该名称.

您甚至可以在一行中获得具有给定年龄的所有人的列表:

[name for name, age in mydict.items() if age == search_age]
Run Code Online (Sandbox Code Playgroud)

或者如果每个年龄只有一个人:

next((name for name, age in mydict.items() if age == search_age), None)
Run Code Online (Sandbox Code Playgroud)

None如果没有那个年龄的人,它会给你.

最后,如果时间dict很长并且你使用的是Python 2,你应该考虑使用.iteritems()而不是.items()像Cat Plus Plus那样在他的答案中使用,因为它不需要复制列表.

  • 除非你的惯常行为看起来很年轻,所以在这种情况下,`dict`是有道理的. (9认同)
  • 正确,但是如果你要进行线性搜索,你也可以用一对列表替换`dict`. (8认同)
  • 假定每个年龄段只有一个人似乎是奇怪的,另一方面,每个人只有一个年龄段是完全合乎逻辑的。 (2认同)

Pat*_*ick 64

我认为指出哪种方法最快,以及在什么情况下会很有趣:

这是我跑的一些测试(在2012 MacBook Pro上)

>>> 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)]
Run Code Online (Sandbox Code Playgroud)

profile.run()每种方法的结果100000次:

方法1:

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

方法2:

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

方法3:

>>> profile.run("for i in range(0,100000): method3(list,16)")
     400004 function calls in 2.125 seconds
Run Code Online (Sandbox Code Playgroud)

所以这表明,对于一个小字典,方法1是最快的.这很可能是因为它返回第一个匹配,而不是像方法2那样的所有匹配(参见下面的注释).


有趣的是,在我有2700个条目的dict上执行相同的测试,我得到了完全不同的结果(这次运行10000次):

方法1:

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

方法2:

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

方法3:

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

所以这里方法3 快得多.只是显示你的dict的大小将影响你选择的方法.

注意:方法2返回所有名称的列表,而方法1和3仅返回第一个匹配.我没有考虑内存使用情况.我不确定方法3是否创建了2个额外的列表(keys()和values())并将它们存储在内存中.

  • 只是一个更新:似乎dict.values()和dict.keys()都返回引用原始dict中对象的列表,因此方法3也是使用最少内存的那个(它只创建两个瘦列表对象)它包含了dicts的内容,而其他的则创建了迭代器项 (6认同)
  • @Martijn @Patrick,从python 3.6开始,dict_keys dict_values不再具有索引属性,你需要先将其转换为列表,我猜这会占用内存(方法3)。所以它最终就像 `list(dict.keys())[list(dict.values()).index(search_age)]` (2认同)
  • @OrsirisdeJong `dict.keys()` 等是*字典视图对象*,并且在所有 Python 3 版本中都是如此,而不仅仅是从 3.6 开始。不要将它们变成列表,使用“next((k for k, v in dict.items() if v == search_age), None)”来查找匹配项。 (2认同)
  • @MartijnPieters 事实上,你的解决方案比列表消耗的内存要少得多,并且可以很好地替代方法 3。只是一件事,你在反转 k 和 v 时犯了一个错误。正确的版本应该是“next((k for k, v in dict.items() if v == search_age), None)”。不管怎样,谢谢你的回答;) (2认同)

fan*_*nny 45

一行版本:(我是旧词典,p是反向词典)

解释:i.keys()和i.values()分别返回两个包含字典的键和值的列表.zip函数能够将列表绑定在一起以生成字典.

警告:仅当值可以清除且唯一时,这才有效.

p = dict(zip(i.values(),i.keys()))
Run Code Online (Sandbox Code Playgroud)

  • ......并且没有重复值时. (13认同)
  • 是的,这会起作用:http://stackoverflow.com/questions/835092/python-dictionary-are-keys-and-values-always-the-same-order (2认同)
  • 美丽.在上面的评论中,当然它只在没有重复值的情况下才有效,但是,启动这个线程的问题假设我们有一对一的函数,所以假设这个假设,这是最优雅的到目前为止的反应 (2认同)
  • 扩展可哈希值:如果您的值是列表/集合,请将它们转换为元组才能正常工作(它们仍然需要是唯一的)。 (2认同)

Jel*_*len 24

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

或更好

{k:v for k, v in a.items() if v == 1}
Run Code Online (Sandbox Code Playgroud)

  • 如果有另一个密钥保持相同的a值怎么办?可能是pythonic方式.但不是一个好主意. (4认同)

小智 20

lKey = [key for key, value in lDictionary.iteritems() if value == lValue][0]
Run Code Online (Sandbox Code Playgroud)


joh*_*hun 12

试试这个单行翻译字典:

reversed_dictionary = dict(map(reversed, dictionary.items()))
Run Code Online (Sandbox Code Playgroud)


And*_*yko 11

您可以通过使用获取密钥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)]
Run Code Online (Sandbox Code Playgroud)

  • 你没有在下一行使用定义的`search_age` var ...也许你应该用`search_age`替换`value`? (2认同)
  • 我得到这个错误:'dict_values'对象没有属性'index' (2认同)

Sak*_*sem 11

我们可以得到Keydict是:

def getKey(dct,value):
     return [key for key in dct if (dct[key] == value)]
Run Code Online (Sandbox Code Playgroud)

  • 简单易懂,适用于独特的价值。 (2认同)

Raf*_*ero 10

我发现这个答案非常有效,但对我来说仍然不容易阅读.

为了使其更清晰,您可以反转键和字典的值.这是使键的值和值的键,因为看到这里.

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

要么

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

这与其他答案基本相同.

  • 如果您有重复的值,例如“{'george':16,'amber':19,'jack':16}”,这可能不起作用 (2认同)
  • 或者你可以在 Python 3 中执行此操作:`[k for k, v indictionary.items() if v == 16])` (2认同)

小智 10

使用列表理解的一行解决方案,如果该值可能多次出现,则返回多个键。

[key for key,value in mydict.items() if value == 16]
Run Code Online (Sandbox Code Playgroud)


Dei*_*ian 9

这是我对这个问题的看法.:)我刚开始学习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
Run Code Online (Sandbox Code Playgroud)

.

#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's 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
Run Code Online (Sandbox Code Playgroud)

.

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

Provide age: 19

amber 19
Garry 19

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

Execution Successful!
Run Code Online (Sandbox Code Playgroud)


Saf*_*lla 9

如果要按值查找键,可以使用字典理解来创建查找字典,然后使用该字典从值中查找键.

lookup = {value: key for key, value in self.data}
lookup[value]
Run Code Online (Sandbox Code Playgroud)


Axe*_*xel 7

考虑使用熊猫.正如William McKinney的"用于数据分析的Python"中所述

考虑系列的另一种方式是作为固定长度的有序字典,因为它是索引值到数据值的映射.它可以在许多你可能使用dict的环境中使用.

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

要查询您的系列,请执行以下操作:

lookup_list[lookup_list.values == 19]
Run Code Online (Sandbox Code Playgroud)

产量:

Out[1]: 
amber    19
dtype: int64
Run Code Online (Sandbox Code Playgroud)

如果您需要对输出执行任何其他操作,将答案转换为列表可能会有用:

answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
Run Code Online (Sandbox Code Playgroud)


小智 6

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

dict((v,k) for k,v in d.items()).get(16)
Run Code Online (Sandbox Code Playgroud)

输出如下:

-> prints george
Run Code Online (Sandbox Code Playgroud)


shi*_*hir 6

这里,recover_key需要字典和值才能在字典中查找.然后我们遍历字典中的键并与值的键进行比较并返回该特定键.

def recover_key(dicty,value):
    for a_key in dicty.keys():
        if (dicty[a_key] == value):
            return a_key
Run Code Online (Sandbox Code Playgroud)


Bre*_*ett 6

get_key = lambda v, d: next(k for k in d if d[k] is v)
Run Code Online (Sandbox Code Playgroud)


小智 5

for name in mydict:
    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
Run Code Online (Sandbox Code Playgroud)


Car*_*ard 5

my_dict = {'A': 19, 'B': 28, 'carson': 28}
search_age = 28
Run Code Online (Sandbox Code Playgroud)

只拿一个

name = next((name for name, age in my_dict.items() if age == search_age), None)
print(name)  # 'B'
Run Code Online (Sandbox Code Playgroud)

获取多个数据

name_list = [name for name, age in filter(lambda item: item[1] == search_age, my_dict.items())]
print(name_list)  # ['B', 'carson']
Run Code Online (Sandbox Code Playgroud)


Fra*_*ang 5

我瞥见了所有答案,没有提到简单地使用列表理解

这个 Pythonic单行解决方案可以返回任意数量给定值的所有键(在 Python 3.9.1 中测试):

>>> dictionary = {'george' : 16, 'amber' : 19, 'frank': 19}
>>>
>>> age = 19
>>> name = [k for k in dictionary.keys() if dictionary[k] == age]; name
['george', 'frank']
>>>
>>> age = (16, 19)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
['george', 'amber', 'frank']
>>>
>>> age = (22, 25)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
[]
Run Code Online (Sandbox Code Playgroud)