我想做类似的事情:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
如何检查dict foo中是否同时包含“ foo”和“ bar”?
我想做类似的事情:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
如何检查dict foo中是否同时包含“ foo”和“ bar”?
Answers:
好吧,你可以这样做:
>>> if all (k in foo for k in ("foo","bar")):
... print "They're there!"
...
They're there!
set
更好。像往常一样...测量它!-)
if {"foo", "bar"} <= myDict.keys(): ...
如果您仍在使用Python 2,则可以执行
if {"foo", "bar"} <= myDict.viewkeys(): ...
如果您仍然使用的是旧版本<= 2.6的Python,则可以调用set
dict,但是它将遍历整个dict以构建集合,这很慢:
if set(("foo", "bar")) <= set(myDict): ...
set(("foo","bar")) <= myDict.keys()
避免了临时设置,因此速度更快。对于我的测试,当查询为10个项目时,其速度与使用全部速度差不多。但是随着查询变大,它变得越来越慢。
if {'foo', 'bar'} <= set(myDict): ...
输入您自己的D和Q值
>>> from timeit import Timer
>>> setup='''from random import randint as R;d=dict((str(R(0,1000000)),R(0,1000000)) for i in range(D));q=dict((str(R(0,1000000)),R(0,1000000)) for i in range(Q));print("looking for %s items in %s"%(len(q),len(d)))'''
>>> Timer('set(q) <= set(d)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632499
0.28672504425048828
#This one only works for Python3
>>> Timer('set(q) <= d.keys()','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632084
2.5987625122070312e-05
>>> Timer('all(k in d for k in q)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632219
1.1920928955078125e-05
d.viewkeys()
做出set(q) <= d.viewkeys()
。
Python 2.7.5
也有d.keys()
方法。
set(q) <= ...
TypeError: can only compare to a set
。抱歉! :))
d.viewkeys() >= set(q)
。我来这里是为了找出订单为什么重要!
您不必将左侧包裹在一组中。您可以这样做:
if {'foo', 'bar'} <= set(some_dict):
pass
这也比all(k in d...)
解决方案要好。
使用集:
if set(("foo", "bar")).issubset(foo):
#do stuff
或者:
if set(("foo", "bar")) <= set(foo):
#do stuff
set(d)
与set(d.keys())
(没有d.keys()
构造中间列表的)相同
这个怎么样:
if all([key in foo for key in ["foo","bar"]]):
# do stuff
pass
all
。
虽然我喜欢Alex Martelli的答案,但对我来说似乎不是Pythonic。也就是说,我认为成为Pythonic的重要部分是易于理解。有了这个目标,<=
并不容易理解。
虽然字符更多,但issubset()
按照卡尔·福格特兰(Karl Voigtland)的答案所建议的用法更容易理解。由于该方法可以将字典用作参数,因此一个简短的,可理解的解决方案是:
foo = {'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4}
if set(('foo', 'bar')).issubset(foo):
#do stuff
我想用{'foo', 'bar'}
代替set(('foo', 'bar'))
,因为它更短。但是,这不是很容易理解,我认为花括号像字典一样容易被混淆。
Alex Martelli的解决方案set(queries) <= set(my_dict)
是最短的代码,但可能不是最快的。假设Q = len(查询)和D = len(my_dict)。
这需要O(Q)+ O(D)来创建两个集合,然后(一个希望!)仅O(min(Q,D))进行子集测试-当然,假设Python进行了查找是O(1)-这是最坏的情况(当答案为True时)。
休格布朗(et al?)的生成器解all(k in my_dict for k in queries)
为最坏情况O(Q)。
复杂因素:
(1)基于集合的小工具中的循环全部以C速度完成,而基于Any的小工具则在字节码上循环。
(2)基于任何内容的小工具的调用者都可以使用任何失败概率的知识来对查询项目进行相应的排序,而基于集合的小工具则不允许这样的控制。
与往常一样,如果速度很重要,则在操作条件下进行基准测试是一个好主意。
您可以使用.issubset()以及
>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>
如果您想:
然后:
from operator import itemgetter
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
keys = ("foo","bar")
getter = itemgetter(*keys) # returns all values
try:
values = getter(foo)
except KeyError:
# not both keys exist
pass
并不是说这不是您没有想到的事情,但是我发现最简单的事情通常是最好的:
if ("foo" in foo) and ("bar" in foo):
# do stuff
就我的观点而言,所有给定的选项都有两种易于理解的方法。因此,我的主要标准是具有非常易读的代码,而不是非常快速的代码。为了使代码易于理解,我更喜欢给定可能性:
在下面的测试中,“ var <= var2.keys()”的执行速度更快,这一事实我更喜欢。
import timeit
timeit.timeit('var <= var2.keys()', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"}')
0.1745898080000643
timeit.timeit('var.issubset(var2)', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"};')
0.2644960229999924
>>> ok
{'five': '5', 'two': '2', 'one': '1'}
>>> if ('two' and 'one' and 'five') in ok:
... print "cool"
...
cool
这似乎有效
()
首先会评估并得出结果True
,然后再检查是否True in ok
。这实际上如何工作?