关于python:在字典中按值获取密钥

Get key by value in dictionary

我做了一个函数,它将查找Dictionary中的年龄,并显示匹配的名称:

1
2
3
4
5
6
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。我知道这是不正确的,但我不知道如何让它向后搜索。


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

或者在python 3.x中:

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

基本上,它在一个列表中分离字典的值,找到您拥有的值的位置,并在该位置获取键。

关于python3中的keys().values():python:从dict获取值列表的最简单方法?


没有。dict不打算这样使用。

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


如果您同时需要姓名和年龄,您应该使用.items(),它将为您提供键(key, value)元组:

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

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

如果你通常要按年龄查找,而且没有两个人的年龄相同,那么你也应该考虑颠倒字典:

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

这样你就可以通过做来查找一个年龄段的名字

1
mydict[search_age]

我把它叫做mydict,而不是list,因为list是一个内置类型的名称,你不应该将这个名称用于其他任何东西。

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

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

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

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

如果没有这个年龄的人,它只会给你一个(6)。

最后,如果dict很长,而您使用的是python 2,那么您应该考虑使用.iteritems()而不是.items(),就像cat plus在其答案中所做的那样,因为它不需要复制列表。


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

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

1
2
3
4
5
6
7
8
9
10
>>> 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:

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

方法2:

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

方法3:

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

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

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

方法1:

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

方法2:

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

方法3:

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

所以在这里,方法3要快得多。只需显示听写的大小就会影响您选择的方法。

笔记:方法2返回所有名称的列表,而方法1和3只返回第一个匹配项。我没有考虑过记忆的使用。我不确定方法3是否创建了两个额外的列表(keys()和values())并将它们存储在内存中。


单行本:(我是一本旧字典,P是一本颠倒的字典)

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

警告:只有在值可哈希且唯一时,此操作才有效。

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


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

或更好

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


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


您可以使用dict.keys()dict.values()list.index()方法获取密钥,见下面的代码示例:

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


这是我对这个问题的看法。:)我刚开始学习Python,所以我称之为:

"初学者可以理解"的解决方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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

.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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

.

1
2
3
4
5
6
7
8
9
10
11
#Results
Running: *\test.py (Thu Jun 06 05:10:02 2013)

Provide age: 19

amber 19
Garry 19

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

Execution Successful!


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

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


尝试这一行来反转字典:

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


考虑使用熊猫。如William McKinney的"数据分析用python"所述。

Another way to think about a Series is as a fixed-length, ordered
dict, as it is a mapping of index values to data values. It can be
used in many contexts where you might use a dict.

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

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

1
lookup_list[lookup_list.values == 19]

收益率:

1
2
3
Out[1]:
amber    19
dtype: int64

如果您需要对转换将答案放入列表中可能很有用:

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


我觉得这个答案很有效,但对我来说还是不容易理解的。

为了更清楚地说明这一点,您可以反转字典的键和值。这将使键值和值成为键,如图所示。

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

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

这与另一个答案基本相同。


在这里,recover关键字使用字典和值在字典中查找。然后循环使用字典中的键,并与值的键进行比较,然后返回该特定键。

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


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

1
2
3
4
5
6
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


1
2
3
4
5
def get_Value(dic,value):
    for name in dic:
        if dic[name] == value:
            del dic[name]
            return name

答案是,但也可以用一个花哨的"地图/减少"使用来完成,例如:

1
2
3
4
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()))

这是我的看法。这有利于显示多个结果,以防需要一个结果。所以我也加入了这个名单

1
2
3
4
5
6
7
8
9
10
11
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[element]其中d是dictionary对象,等于要查找的键,则可以执行一些代码。

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

我知道这是老的,但你可以很容易地找到与你的搜索年龄使用列表理解列表中的所有人。

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

我希望这可能有帮助…

1
2
3
for key in list:
   if list[key] == search_value:
       return key

有时可能需要int():

1
2
3
4
5
6
7
8
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

cat plus提到,这不是一本词典的用途。这就是为什么:

字典的定义类似于数学中的映射。在这种情况下,dict是k(键集)到v(值)的映射,但反之亦然。如果取消对dict的引用,则只需要返回一个值。但是,不同的键映射到相同的值是完全合法的,例如:

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

当你根据一个键的对应值查找它时,你实际上是在颠倒字典。但映射不一定是可逆的!在本例中,请求与v1对应的键可以生成k1或k3。你应该两个都还吗?只找到第一个?这就是为什么indexof()对于字典是未定义的。

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


你需要用一本字典和那本字典的反面。这意味着您需要另一个数据结构。如果您在python 3中,请使用enum模块;但是如果您使用python 2.7,请使用enum34,它是为python 2而移植的。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

1
2
3
d= {'george':16,'amber':19}

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

输出如下:

1
-> prints george


已经回答过了,但是由于有几个人提到了颠倒字典,下面是您如何在一行(假设1:1映射)和一些不同的性能数据中实现这一点:

Python 2.6:

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

2.7 +:

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

如果您认为它不是1:1,您仍然可以用几行创建一个合理的反向映射:

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

这有多慢:比简单的搜索慢,但不像你想象的那么慢——在一个"直"的100000词条字典上,"快"的搜索(即寻找一个应该在键的早期的值)比反转整个字典快10倍左右,"慢"的搜索(接近结尾)快4-5倍左右。因此,在最多10次查找之后,它是自己付费的。

第二个版本(每个项目都有列表)与简单版本相比大约需要2.5倍的时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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(),可能不需要创建/遍历整个值列表。在实践中,结果是…奇怪…

1
2
3
4
5
6
7
8
9
10
11
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)。但是,对于列表末尾附近的较大偏移量,其速度明显较慢(15.1 ms与相同的1.48 ms)。低端的小额储蓄不值得高端的成本,imho。


1
2
3
4
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.

多次使用:

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


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

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

当然,你的名字太离谱了,看起来像是打印了一个时代,但它确实打印了这个名字。由于您是通过名称访问的,因此如果您写下以下内容,则更容易理解:

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

更好的是:

1
2
3
4
5
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

下面是一个同时适用于Python2和Python3的解决方案:

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

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

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

或者更一般地说是一个工厂,它将为一个或多个列表创建按年龄命名的查找方法

1
2
3
4
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]

所以你可以这样做:

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

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


只有我在《江户记》1(7)和《江户记》1(8)中的回答。

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

我们可以通过以下方式获得dictKey

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

我尽可能多地阅读解决方案,以防给出重复的答案。但是,如果您正在处理一个字典,其中的值包含在列表中,并且如果您想要获得具有特定元素的键,可以这样做:

1
2
3
4
5
6
7
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个的名称。

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

这也适用于多个值。


一个简单的方法可以是:

1
2
3
4
5
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

这将返回具有匹配搜索年龄值的键列表。如果需要,还可以将"list==searchu age"替换为任何其他条件语句。