在字典中按值获取键

我做了一个函数,它将在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。我知道这是不正确的,但我不知道如何让它向后搜索。

2288996 次浏览

如果你想要名字和年龄,你应该使用.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)

如果没有那个年龄的人,它会给你0。

最后,如果dict很长并且您使用的是Python 2,您应该考虑使用.iteritems()而不是.items(),因为它不需要复制列表。

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

dictionary = {'george': 16, 'amber': 19}search_age = input("Provide age")for name, age in dictionary.items():  # for name, age in dictionary.iteritems():  (for Python 2.x)if age == search_age:print(name)
key = next((k for k in my_dict if my_dict[k] == val), None)
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
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()我怎么能从字典的值列表?

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

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

def method1(dict, search_age):for name, age in dict.iteritems():if age == search_age:return name
def method2(dict, search_age):return [name for name,age in dict.iteritems() if age == search_age]
def method3(dict, search_age):return dict.keys()[dict.values().index(search_age)]

每个方法上的profile.run()结果100,000次:

方法一:

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

方法二:

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

方法三:

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

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


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

方法一:

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

方法二:

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

方法三:

>>> 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())并将它们存储在内存中。

它已经回答了,但它可以通过花哨的map/duce使用来完成,例如:

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

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

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

#Code without comments.
list1 = {'george':16,'amber':19, 'Garry':19}search_age = raw_input("Provide age: ")printsearch_age = int(search_age)
listByAge = {}
for name, age in list1.items():if age == search_age:age = str(age)results = name + " " +ageprint results
age2 = int(age)listByAge[name] = listByAge.get(name,0)+age2
printprint 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.printprint listByAge

.

#ResultsRunning: *\test.py (Thu Jun 06 05:10:02 2013)
Provide age: 19
amber 19Garry 19
{'amber': 19, 'Garry': 19}
Execution Successful!

单行版本:(i是旧字典,p是反向字典)

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

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

警告:仅当值可散列且唯一时才有效。

已经回答过了,但是因为有几个人提到了反转字典,下面是你如何在一行(假设1:1映射)和一些不同的perf数据中做到这一点:

python2.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 itIn [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应该更快,因为我们可以使用迭代值(),可能不必创建/遍历整个值列表。在实践中,结果是…奇怪的…

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.1ms vs.相同的1.48mS)。在低端的小节省不值得高端的成本,我的意思是。

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

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

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

当你通过对应的值查找一个键时,你本质上是在反转字典。但是映射不一定是可逆的!在这个例子中,要求与v1对应的键可能会产生k1或k3。你应该同时返回两个吗?只是找到的第一个?这就是为什么indexof()对字典来说是未定义的。

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

这是我对它的看法。这对于显示多个结果很有用,以防万一你需要一个。所以我也添加了列表

myList = {'george':16,'amber':19, 'rachel':19,'david':15 }                         #Setting the dictionaryresult=[]                                       #Making ready of the result listsearch_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 resultsprint(res)

就这样…

d= {'george':16,'amber':19}
dict((v,k) for k,v in d.items()).get(16)

输出如下:

-> prints george

有时可能需要int():

titleDic = {'Фильмы':1, 'Музыка':2}
def categoryTitleForNumber(self, num):search_title = ''for title, titleNum in self.titleDic.items():if int(titleNum) == int(num):search_title = titlereturn search_title

这是一个在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,因为前者是预定义的类型。

没有简单的方法通过“查找”值来查找列表中的键。但是,如果您知道值,遍历键,您可以通过元素在字典中查找值。如果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)

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

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

这就是你如何访问字典来做你想做的事情:

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

您需要使用字典并反转该字典。这意味着您需要另一个数据结构。如果您使用的是python 3,请使用enum模块,但如果您使用的是python 2.7,请使用为python 2反向移植的enum34

示例:

from enum import Enum
class Color(Enum):red = 1green = 2blue = 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.value1

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

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

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

一个简单的方法可以是:

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值的键的列表。如果需要,您还可以将“list==search_age”替换为任何其他条件语句。

考虑使用Pandas。正如William McKinney的“Python for Data Analysis”中所述

考虑序列的另一种方式是作为固定长度的有序序列字典,因为它是索引值到数据值的映射。它可以是在许多情况下,你可能会使用一个字典。

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

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

lookup_list[lookup_list.values == 19]

其结果为:

Out[1]:amber    19dtype: int64

如果您需要对输出进行任何其他转换在一个列表中找到答案可能很有用:

answer = lookup_list[lookup_list.values == 19].indexanswer = pd.Index.tolist(answer)
get_key = lambda v, d: next(k for k in d if d[k] is v)

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

def getKey(dct,value):return [key for key in dct if (dct[key] == value)]
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 )]

我发现这个回答非常有效,但对我来说不是很容易阅读。

为了使它更清楚,您可以反转字典的键和值。这是使键值和值键,如这里所示。

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

或者对于Python 3,(感谢@kkgarg)

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

print(res.get(16)) # Prints george

这与其他回答基本相同。

试试这个单行代码来反转字典:

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

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

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)

这也适用于多个值。

我的答案是lambdafilter

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

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

这是我班上的字典

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

实例化您的字典

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

最后调用你的字典键

patched = local_config.get("devops")
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']

我最终用一个函数来完成它。这样你就可以避免做完整的循环,直觉说它应该比其他提供的解决方案更快。

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

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

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

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

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

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

这个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[]

这是一个真正的“可逆字典”,基于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),从键中调用值,只需像往常一样执行字典['key'],这是一个用法示例:

rev_dict = ReversibleDict(enforce_unique=True)rev_dict["a"] = 1rev_dict["b"] = 2rev_dict["c"] = 3print("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

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

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…我尝试了几种循环和迭代器,OK…他们的工作,但它不是简单的一行解决方案,我会使用快速的结果…所以我只是交换和解决方案找到。如果我错过了什么,请让我知道删除我的答案。

我一直在寻找同样的问题,最后得到了我的变体:found_key = [a[0] for a in dict.items() if a[1] == 'value'][0]

仅适用于键具有唯一值的情况(这是我的情况)。

dict_a = {'length': 5, 'width': 9, 'height': 4}
# get the key of specific value 5key_of_value = list(dict_a)[list(dict_a.values()).index(5)]print(key_of_value)  # length
# get the key of minimum valuekey_min_value = list(dict_a)[list(dict_a.values()).index(sorted(dict_a.values())[0])]print(key_min_value)  # height
# get the key of maximum valuekey_max_value = list(dict_a)[list(dict_a.values()).index(sorted(dict_a.values(), reverse=True)[0])]print(key_max_value)  # width

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

[key for key,value in mydict.items() if value == 16]

正如有人提到的,可能有不止一个键具有相同的值,就像下面的my_dict。此外,可能没有匹配的键。

my_dict ={'k1':1,'k2':2, 'k3':1, 'k4':12, 'k5':1, 'k6':1, 'k7':12}

这里有三种找到钥匙的方法,一种用于最后一次命中,两种用于第一次命中。

def find_last(search_value:int, d:dict):    
return [x for x,y in d.items() if y==search_value].pop()
def find_first1(search_value:int, d:dict):return next(filter(lambda x: d[x]==search_value, d.keys()), None)
def find_first2(search_value:int, d:dict):return next(x for x,y in  d.items() if y==search_value)

其中find_first1比其他键快一点,如果没有匹配的键,将返回None