在字典中按值获取密钥

时间:2011-11-05 21:09:18

标签: python 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

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

41 个答案:

答案 0 :(得分:482)

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

基本上,它会在列表中分离字典的值,找到您所拥有的值的位置,并在该位置获取密钥。

有关Python 3中keys().values()的更多信息:Python: simplest way to get list of values from dict?

答案 1 :(得分:448)

没有。 dict不打算以这种方式使用。

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

答案 2 :(得分:215)

如果您希望名称​​和都是年龄,那么您应该使用.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是内置类型的名称,您不应该将该名称用于其他任何内容。< / p>

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

[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在他的回答中做了,因为它没有不需要复制清单。

答案 3 :(得分:61)

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

这是我跑过的一些测试(在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)]

每个方法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

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


有趣的是,对于我有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())并将它们存储在内存中。

答案 4 :(得分:41)

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

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

警告:仅当值具有可清除且唯一时才会起作用。

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

答案 5 :(得分:23)

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}

答案 6 :(得分:19)

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

答案 7 :(得分:10)

您可以使用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)]

答案 8 :(得分:9)

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

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

答案 9 :(得分:9)

尝试以下一种方法来反转字典:

import moment = require('moment');

console.log(moment().format('LLLL'));

答案 10 :(得分: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

#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

#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 :(得分:7)

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

为了使其更清晰,您可以反转键和字典的值。这是键值和值键,如here所示。

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]

与其他answer基本相同。

答案 12 :(得分:6)

考虑使用熊猫。正如William McKinney的“用于数据分析的Python”

所述
  

考虑系列的另一种方式是定长,有序   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)

答案 13 :(得分:6)

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

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

答案 14 :(得分:5)

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

答案 15 :(得分: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
[]

答案 16 :(得分:4)

我知道这已经过时了,但您可以使用列表理解轻松找到列表中所有搜索年龄的人。

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

答案 17 :(得分:4)

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

答案 18 :(得分:4)

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

答案 19 :(得分:4)

它得到了回答,但可以使用花哨的'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()))

答案 20 :(得分:3)

通过查找&#39;找不到列表中的密钥是没有简单的方法。价值。但是,如果您知道该值,则遍历键,您可以通过元素在字典中查找值。如果D [element]其中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 :(得分:3)

我希望这可能会有所帮助......

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

答案 22 :(得分:3)

这是我的看法。这对于显示多个结果非常有用,以防您需要。所以我也添加了列表

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)

那就是......

答案 23 :(得分:2)

这是一个奇怪的问题,因为第一条评论提供了完美的答案。
基于提供的样本数据示例

dictionary = {'george': 16, 'amber': 19}
print(dictionary["george"])

它回来了

16

所以你想要相反的
输入“16”并得到“乔治” 所以只需交换键、值和 presto

dictionary = {'george': 16, 'amber': 19}
inv_dict = {value:key for key, value in dictionary.items()}
print(inv_dict[16])

我处于完全相反的位置,因为我有一本像这样的字典

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

并且我试图喂食“乔治”并获得 16 ……我尝试了几种循环和迭代器,它们还可以……它们可以工作,但这不是我用来快速获得结果的简单的单行解决方案。 ..所以我只是交换并找到了解决方案。
如果我错过了什么,请告诉我删除我的答案。

答案 24 :(得分:2)

有时可能需要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

答案 25 :(得分:2)

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

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

输出如下:

-> prints george

答案 26 :(得分:2)

Cat Plus Plus提到这不是字典的使用方式。原因如下:

字典的定义类似于数学中的映射。在这种情况下,dict是K(键组)到V(值)的映射 - 但反之亦然。如果你取消引用dict,你希望得到一个返回的值。但是,将不同的键映射到相同的值是完全合法的,例如:

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

当你通过它的相应值查找一个键时,你实际上是在反转字典。但是映射不一定是可逆的!在该示例中,要求对应于v1的密钥可以产生k1或k3。你应该两个回来吗?刚发现的第一个?这就是为词典定义indexof()的原因。

如果您知道自己的数据,就可以这样做。但是API不能假设任意字典是可逆的,因此缺少这样的操作。

答案 27 :(得分:2)

您需要使用字典并反转该字典。这意味着您需要另一种数据结构。如果您使用的是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 

答案 28 :(得分:2)

my_dict = {'A': 19, 'B': 28, 'carson': 28}
search_age = 28

只吃一个

name = next((name for name, age in my_dict.items() if age == search_age), None)
print(name)  # 'B'

获取多个数据

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

答案 29 :(得分:1)

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 )]

答案 30 :(得分:1)

这是一个真正的“可逆字典”,基于 Adam Acosta 的解决方案,但强制 val-to-key 调用是唯一的,并且可以轻松地从值中返回键:

from collections import UserDict


class ReversibleDict(UserDict):
    def __init__(self, enforce_unique=True, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.val_to_keys = {}
        self.check_val = self.check_unique if enforce_unique else lambda x: x

    def __setitem__(self, key, value):
        self.check_val(value)
        super().__setitem__(key, value)
        self.val_to_keys[value] = key

    def __call__(self, value):
        return self.val_to_keys[value]

    def check_unique(self, value):
        assert value not in self.val_to_keys, f"Non unique value '{value}'"
        return value

如果你想强制字典值的唯一性,确保设置enforce_unique=True。从值中获取键只需执行 rev_dict(value),从键中调用值就像往常一样 dict['key'],这是一个用法示例:

rev_dict = ReversibleDict(enforce_unique=True)
rev_dict["a"] = 1
rev_dict["b"] = 2
rev_dict["c"] = 3
print("full dictinoary is: ", rev_dict)
print("value for key 'b' is: ", rev_dict["b"])
print("key for value '2' is: ", rev_dict(2))
print("tring to set another key with the same value results in error: ")
rev_dict["d"] = 1

答案 31 :(得分:1)

我意识到已经很长时间了,最​​初的提问者可能不再需要任何答案,但是如果您确实可以控制此代码,那么这些都不是好的答案。您只是使用了错误的数据结构。这是双向 dict 用例的完美说明:

>>> from collections import defaultdict, UserDict
>>> class TwoWayDict(UserDict):
...     def __init__(self, *args, **kwargs):
...         super().__init__(*args, **kwargs)
...         self.val_to_keys = defaultdict(list)
...     def __setitem__(self, key, value):
...         super().__setitem__(key, value)
...         self.val_to_keys[value].append(key)
...     def get_keys_for_val(self, value):
...         return self.val_to_keys[value]
... 
>>> d = TwoWayDict()
>>> d['a'] = 1
>>> d['b'] = 1
>>> d.get_keys_for_val(1)
['a', 'b']

为插入增加了微不足道的开销,但您保持恒定时间查找,除了现在在两个方向上。无需每次需要时从头开始构建反向映射。只需随时存储并根据需要访问它。

此外,其中许多答案甚至都不正确,因为很明显,许多人可能有相同的年龄,但他们只返回第一个匹配的键,而不是全部。

答案 32 :(得分:1)

我尝试阅读尽可能多的解决方案,以防止给出重复的答案。但是,如果您正在使用字典,其值包含在列表中,并且想要获取具有特定元素的键,则可以执行以下操作:

d = {'Adams': [18, 29, 30],
     'Allen': [9, 27],
     'Anderson': [24, 26],
     'Bailey': [7, 30],
     'Baker': [31, 7, 10, 19],
     'Barnes': [22, 31, 10, 21],
     'Bell': [2, 24, 17, 26]}

现在,让我们查找其值中包含24个名称。

for key in d.keys():    
    if 24 in d[key]:
        print(key)

这同样适用于多个值。

答案 33 :(得分:1)

已经得到了解答,但由于有几个人提到了翻译字典,这里是你如何在一行(假设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()]
这有多慢:比简单搜索慢,但不像你想象的那么慢 - 在'直'100000入口词典上,'快速'搜索(即寻找应该在早期的值)键)比翻转整个词典快大约10倍,而“慢”搜索(朝向末尾)大约快4-5倍。因此,在最多大约10次查找之后,它自己付出了代价。

第二个版本(每个项目的列表)大约是简单版本的2.5倍。

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 * m * S)。然而,对于靠近列表末尾的大偏移量,它显着变慢(相对于相同的1.48mS,为15.1ms)。低端的小额节省不值得高端的成本,imho。

答案 34 :(得分:1)

我们可以通过以下方式获取Key dict

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

答案 35 :(得分:1)

这是您访问字典以执行所需操作的方式:

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

答案 36 :(得分:0)

只有我在lambdafilter中的回答。

filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age  , dictionary )

答案 37 :(得分:0)

在我的情况下,最简单的方法是在代码中实例化自变量,然后可以像下面这样从中调用键

这是我上课的字典

class Config:

def local(self):
    return {
        "temp_dir": "/tmp/dirtest/",
        "devops": "Mansur",
    }

实例化字典

config =  vars.Config()
local_config = config.local()

最后调用您的字典键

patched = local_config.get("devops")

答案 38 :(得分:0)

我最终用一个函数来完成它。这样,您可以避免执行完整循环,并且 intuition 表示它应该比提出的其他解决方案更快。

def get_key_from_value(my_dict, to_find):

    for k,v in my_dict.items():
        if v==to_find: return k

    return None

答案 39 :(得分:0)

这是一个适用于Python 2和Python 3的解决方案:

dict((v, k) for k, v in list.items())[search_age]

直到[search_age]构造反向字典的部分(其中值是键,反之亦然)。 您可以创建一个帮助方法,它将缓存这个反向字典,如下所示:

def find_name(age, _rev_lookup=dict((v, k) for k, v in ages_by_name.items())):
    return _rev_lookup[age]

或甚至更普遍的工厂,它会为您的一个或多个列表创建按年龄名称查找方法

def create_name_finder(ages_by_name):
    names_by_age = dict((v, k) for k, v in ages_by_name.items())
    def find_name(age):
      return names_by_age[age]

所以你可以这样做:

find_teen_by_age = create_name_finder({'george':16,'amber':19})
...
find_teen_by_age(search_age)

请注意,我将list重命名为ages_by_name,因为前者是预定义类型。

答案 40 :(得分:-1)

执行此操作的简单方法可能是:

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

这将返回值与search_age匹配的键列表。您也可以替换&#34; list == search_age&#34;如果需要,可以使用任何其他条件声明。