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

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


当前回答

你可以通过使用dict.keys(), dict.values()和list.index()方法来获取key,参见下面的代码示例:

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

其他回答

如果你想要名字和年龄,你应该使用.items(),它会给你key (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。

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

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():如何从dict获取值列表?

这是你访问字典做你想做的事情的方式:

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

下面是一个在python2和python3中都适用的解决方案:

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

直到[search_age]的部分构造反向字典(其中值是键,反之亦然)。 你可以创建一个helper方法来缓存这个反向字典,就像这样:

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

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

以下是我在一台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次的结果:

方法1:

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

方法2:

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

方法3:

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

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


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

方法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要快得多。这表明字典的大小会影响你选择的方法。

注:

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