【问题标题】:index python dictionary by value [duplicate]按值索引python字典[重复]
【发布时间】:2012-04-04 16:41:15
【问题描述】:

可能重复:
Inverse dictionary lookup - Python

在 Python 中是否有一种内置方法可以按值索引字典。

例如类似:

dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print key where dict[key] == 'apple'

或:

dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print key where 'apple' in dict[key]

还是我必须手动循环播放?

【问题讨论】:

  • 请注意,valuesdict 中是唯一的没有限制,只有keys。当你的字典中有两个相同的键时会发生什么?
  • @Hooked 你的意思是“两个相同的值”吗?
  • @root45 是的,我的意思是相同的“值”而不是“键”,对此感到抱歉。类似:A = {1:'foo',2:'foo'}foo 的倒数应该返回这里?
  • 我想在这种情况下应该返回一个键列表。不过好点。
  • @Ferguzz:给你写了一个适用于所有情况的答案,并返回一个键列表,以便正确处理重复项。

标签: python dictionary


【解决方案1】:

你可以使用list comprehension:

my_dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print [key for key, value in my_dict.items() if value == 'apple']

上面的代码几乎完全符合你的要求:

打印键,其中 dict[key] == 'apple'

列表推导会遍历字典的items method 给出的所有键、值对,并创建一个包含值为“apple”的所有键的新列表。

正如 Niklas 指出的那样,当您的值可能是列表时,这不起作用。由于'apple' in 'pineapple' == True,在这种情况下你必须小心使用in。因此,坚持使用列表理解方法需要进行一些类型检查。因此,您可以使用如下辅助函数:

def equals_or_in(target, value):
    """Returns True if the target string equals the value string or,
    is in the value (if the value is not a string).
    """
    if isinstance(target, str):
        return target == value
    else:
        return target in value

然后,下面的列表推导将起作用:

my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print [key for key, value in my_dict.items() if equals_or_in('apple', value)]

【讨论】:

  • 我相信 OP 想要搜索值而不是键。
  • @Amjith 是的,我脑子里放了个屁。已修复。
  • 在更一般的第二个示例中不起作用
  • 我不会检查字符串类型,而是检查不太可能更改的列表类型,否则您的函数将不适用于例如整数值。此外,您应该使用isinstance 比较type()s 的实例
  • 检查list 类型的问题是您不能再检查集合中的成员资格。正确答案落在哪里取决于 OP。不过,您对isinstance 的看法绝对正确。我会更新的。
【解决方案2】:

您必须手动循环它,但如果您需要反复查找,这是一个方便的技巧:

d1 = {'fruit':'apple','colour':'blue','meat':'beef'}

d1_rev = dict((v, k) for k, v in d1.items())

然后您可以像这样使用反向字典:

>>> d1_rev['blue']
'colour'
>>> d1_rev['beef']
'meat'

【讨论】:

  • 你至少应该提一下最后一行的作用?
  • @bernie:这对 OP 来说并不明显,否则他不会问。一个简单的“构建反向字典(value->key)”就足够了,但是没有任何东西,这有点令人困惑
  • 这不适用于第二个示例,因为列表是可变的,因此不能用作字典键。
  • 如果字典很大,请改用.iteritems()
  • @bernie:仅在 Python 2 中。就目前而言,这适用于 所有 版本的 Python(甚至
【解决方案3】:

您的要求比您意识到的要复杂:

  • 您需要同时处理列表值和普通值
  • 您实际上不需要取回一个密钥,而是一个 密钥列表

你可以分两步解决这个问题:

  1. 规范化字典,使每个值都是一个列表(每个普通值都变成一个单元素)
  2. 构建反向词典

以下函数将解决这个问题:

from collections import defaultdict

def normalize(d):
    return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() }

def build_reverse_dict(d):
    res = defaultdict(list)
    for k,values in normalize(d).items():
        for x in values:
            res[x].append(k)
    return dict(res)

这样使用:

>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'})
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']}
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'})
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']}
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']})
{'duplicate': ['a', 'b']}

因此,您只需构建一次反向字典,然后按值查找并返回键列表。

【讨论】:

  • 我认为res[x] 有错字,因为您从未定义过x
  • @Hooked:谢谢,确实我已经编辑以使其更短并通过这样做打破它......
猜你喜欢
  • 2013-02-13
  • 2021-06-03
  • 1970-01-01
  • 2022-01-07
  • 2020-11-19
  • 1970-01-01
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多