如何根据对应的值过滤字典键
Posted
技术标签:
【中文标题】如何根据对应的值过滤字典键【英文标题】:How to filter dictionary keys based on its corresponding values 【发布时间】:2012-05-16 21:48:01 【问题描述】:我有:
dictionary = "foo":12, "bar":2, "jim":4, "bob": 17
我想遍历这个字典,但是遍历的是值而不是键,所以我可以在另一个函数中使用这些值。
例如,我想测试哪些字典值大于6
,然后将它们的键存储在一个列表中。我的代码如下所示:
list = []
for c in dictionary:
if c > 6:
list.append(dictionary[c])
print list
然后,在一个完美的世界中,list
将包含所有值大于6
的键。
但是,我的 for
循环只是遍历键;我想将其更改为值!
非常感谢任何帮助。 谢谢你
【问题讨论】:
这个问题的标题应该改变,因为你真正想要实现的(并且答案反映了这一点)是在某个子句为真的字典中获取相应值的键。 “”之类的内容可能是更好的选择。 【参考方案1】:>>> d = "foo": 12, "bar": 2, "jim": 4, "bob": 17
>>> [k for k, v in d.items() if v > 6] # Use d.iteritems() on python 2.x
['bob', 'foo']
我只想更新这个答案,以展示@glarrain 的解决方案,我发现自己现在倾向于使用它。
[k for k in d if d[k] > 6]
这是完全交叉兼容的,不需要从.iteritems
(.iteritems
避免在 Python 2 上将列表保存到内存中,这在 Python 3 中已修复)到.items
的混乱更改。
@Prof.Falken 提到了这个问题的解决方案
from six import iteritems
它有效地解决了交叉兼容性问题,但需要您下载包six
但是我不完全同意@glarrain 的观点,即这个解决方案更具可读性,这是有争议的,也许只是个人偏好,尽管 Python 应该只有一种方法来做到这一点。在我看来,这取决于具体情况(例如,您可能有一个很长的字典名称,您不想输入两次,或者您想给值一个更易读的名称或其他原因)
一些有趣的时间安排:
在 Python 2 中,第二种解决方案更快,在 Python 3 中,它们的原始速度几乎完全相同。
$ python -m timeit -s 'd = "foo": 12, "bar": 2, "jim": 4, "bob": 17;' '[k for k, v in d.items() if v > 6]'
1000000 loops, best of 3: 0.772 usec per loop
$ python -m timeit -s 'd = "foo": 12, "bar": 2, "jim": 4, "bob": 17;' '[k for k, v in d.iteritems() if v > 6]'
1000000 loops, best of 3: 0.508 usec per loop
$ python -m timeit -s 'd = "foo": 12, "bar": 2, "jim": 4, "bob": 17;' '[k for k in d if d[k] > 6]'
1000000 loops, best of 3: 0.45 usec per loop
$ python3 -m timeit -s 'd = "foo": 12, "bar": 2, "jim": 4, "bob": 17;' '[k for k, v in d.items() if v > 6]'
1000000 loops, best of 3: 1.02 usec per loop
$ python3 -m timeit -s 'd = "foo": 12, "bar": 2, "jim": 4, "bob": 17;' '[k for k in d if d[k] > 6]'
1000000 loops, best of 3: 1.02 usec per loop
然而,这些只是对小型字典的测试,在 huge 字典中,我很确定没有字典键查找 (d[k]
) 会使 .items
更快。
而且好像是这样的
$ python -m timeit -s 'd = i: i for i in range(-10000000, 10000000);' -n 1 '[k for k in d if d[k] > 6]'
1 loops, best of 3: 1.75 sec per loop
$ python -m timeit -s 'd = i: i for i in range(-10000000, 10000000);' -n 1 '[k for k, v in d.iteritems() if v > 6]'
1 loops, best of 3: 1.71 sec per loop
$ python3 -m timeit -s 'd = i: i for i in range(-10000000, 10000000);' -n 1 '[k for k in d if d[k] > 6]'
1 loops, best of 3: 3.08 sec per loop
$ python3 -m timeit -s 'd = i: i for i in range(-10000000, 10000000);' -n 1 '[k for k, v in d.items() if v > 6]'
1 loops, best of 3: 2.47 sec per loop
【讨论】:
对于 python 2.x,d.iteritems()
AFAIK 会更好。
@hochl 我将其保留为 items
以实现交叉兼容性,但我会在其中发表评论。
或from six import iteritems
【参考方案2】:
这个怎么样:
dictionary = "foo":12, "bar":2, "jim":4, "bob": 17
for val in dictionary.values():
# do something
【讨论】:
如果 OP 不介意,我想删除我的答案。 @jamylak 这绝对是要走的路。【参考方案3】:要获取值,请使用dictionary.values()
要获取键值对,请使用dictionary.items()
【讨论】:
【参考方案4】:在字典中使用items
或iteritems
。比如:
list = []
for k, v in dictionary.iteritems():
if v > 6:
list.append(k)
print list
【讨论】:
【参考方案5】:这取决于您是否要修改字典(添加或删除项目)。如果没有,那么您可以尝试:
for value in dictionary.itervalues(): #this returns a generator
print "do something with the value"
或者,如果您修改字典,则应该遍历值的副本:
for value in dictionary.values(): #this returns a list of values
print "do something with the value"
如果您想要键和值,您可以使用 dictionary.iteritems()
或 dictionary.items()
对对进行迭代
【讨论】:
【参考方案6】:我认为最好的方法(考虑迁移到 Python 3)是
>>> mydict = 'foo': 12, 'bar': 2, 'jim': 4, 'bob': 17
>>> [k for k in mydict if mydict[k] > 6]
['bob', 'foo']
“最佳”的标准是可读性。
(免责声明:我的回答基于 Alex Martelli 对其他问题 https://***.com/a/3744713/556413 和 @jamylak 对这个问题的回答)
【讨论】:
以上是关于如何根据对应的值过滤字典键的主要内容,如果未能解决你的问题,请参考以下文章