如何在一次传递中检查字典中是否有多个键?

2025-04-15 09:20:00
admin
原创
38
摘要:问题描述:我想做这样的事:foo = { 'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4 } if ("foo", "bar") in foo: #do stuff 如何检查foo和是否bar都在 ...

问题描述:

我想做这样的事:

foo = {
    'foo': 1,
    'zip': 2,
    'zam': 3,
    'bar': 4
}

if ("foo", "bar") in foo:
    #do stuff

如何检查foo和是否bar都在 dict 中foo


解决方案 1:

嗯,你可以这样做:

>>> if all(k in foo for k in ("foo","bar")):
...     print "They're there!"
...
They're there!

解决方案 2:

if {"foo", "bar"} <= myDict.keys(): ...

如果你还在使用 Python 2,你可以这样做

if {"foo", "bar"} <= myDict.viewkeys(): ...

如果您仍在使用非常老的 Python <= 2.6,您可以调用set该字典,但它会遍历整个字典来构建集合,这很慢:

if set(("foo", "bar")) <= set(myDict): ...

解决方案 3:

对 3 种替代方案进行简单的基准测试。

输入您自己的 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

解决方案 4:

你不必将左侧包裹在集合中。你可以这样做:

if {'foo', 'bar'} <= set(some_dict):
    pass

这也比解决方案表现更好all(k in d...)

解决方案 5:

使用集合

if set(("foo", "bar")).issubset(foo):
    #do stuff

或者:

if set(("foo", "bar")) <= set(foo):
    #do stuff

解决方案 6:

这应该可行:

if all(key in foo for key in ["foo","bar"]):
    # do stuff
    pass

暗示:

使用方括号来all()进行列表理解:

if all([key in foo for key in ["foo","bar"]]):

不仅是不必要的,而且是有害的,因为它们会阻碍正常的短路行为all()

解决方案 7:

我认为这是最聪明、最 Pythonic 的。

{'key1','key2'} <= my_dict.keys()

解决方案 8:

虽然我喜欢 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')),因为它更短。但是,它不太容易理解,而且我觉得括号很容易让人误认为是字典。

解决方案 9:

检查字典中所有键是否存在:

{'key_1', 'key_2', 'key_3'} <= set(my_dict)

检查字典中是否存在一个或多个键:

{'key_1', 'key_2', 'key_3'} & set(my_dict)

解决方案 10:

Alex Martelli 的解决方案set(queries) <= set(my_dict)是最短的代码,但未必是最快的。假设 Q = len(queries) 且 D = len(my_dict)。

这需要 O(Q) + O(D) 来构成两个集合,然后(希望如此!)只需要 O(min(Q,D)) 来进行子集测试 —— 当然假设 Python 集合查找是 O(1) —— 这是最坏的情况(当答案为 True 时)。

hughdbrown(等人)的生成器解决方案all(k in my_dict for k in queries)是最坏情况的 O(Q)。

复杂因素:

(1)基于集合的小工具中的循环均以 C 速度完成,而基于任意的小工具则循环遍历字节码。

(2)基于任意的小工具的调用者可能能够使用任何失败概率知识来对查询项进行相应的排序,而基于集合的小工具则不允许进行此类控制。

与往常一样,如果速度很重要,那么在操作条件下进行基准测试是一个好主意。

解决方案 11:

您也可以使用.issubset()

>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>

解决方案 12:

简短而甜蜜

{"key1", "key2"} <= {*dict_name}

解决方案 13:

使用 lambda 怎么样?

 if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff

解决方案 14:

如果您想:

  • 还可以获取键的值

  • 查阅多个词典

然后:

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

解决方案 15:

并不是说你没有想到这一点,但我发现最简单的事情通常是最好的:

if ("foo" in foo) and ("bar" in foo):
    # do stuff

解决方案 16:

>>> if 'foo' in foo and 'bar' in foo:
...     print 'yes'
... 
yes

Jason,() 在 Python 中不是必需的。

解决方案 17:

我个人认为,在所有给出的选项中,有两种方法比较容易理解。所以我的主要标准是代码可读性强,而不是运行速度特别快。为了保持代码易懂,我倾向于给出以下可能性:

  • var <= var2.keys()

  • var.issubset(var2)

事实上,在下面的测试中,“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

解决方案 18:

在确定是否只有某些键匹配的情况下,这是有效的:

any_keys_i_seek = ["key1", "key2", "key3"]

if set(my_dict).intersection(any_keys_i_seek):
    # code_here
    pass

还有另一种选择,用于查找是否只有某些键匹配:

any_keys_i_seek = ["key1", "key2", "key3"]

if any_keys_i_seek & my_dict.keys():
    # code_here
    pass

解决方案 19:

检测所有键是否都在字典中的另一种选择:

dict_to_test = { ... }  # dict
keys_sought = { "key_sought_1", "key_sought_2", "key_sought_3" }  # set

if keys_sought & dict_to_test.keys() == keys_sought: 
    # True -- dict_to_test contains all keys in keys_sought
    # code_here
    pass

解决方案 20:

如果您想获取不匹配的物品,这里有一个替代解决方案......

not_existing_keys = [item for item in ["foo","bar"] if item not in foo]
if not_existing_keys:
  log.error('These items are missing', not_existing_keys)

解决方案 21:

my_dict = {
    'name': 'Askavy',
    'country': 'India',
    'age': 30
}

if set(('name', 'country','age')).issubset(my_dict.keys()):
     print("All keys are present in the dictionary") 
else: 
    print("All keys are not present in  the dictionary") 

解决方案 22:

对我来说,简单易用,中间有 None 键和pydash ref

import pydash as _
_.get(d, 'key1.key2.key3.whatevermaybeNone.inthemiddle', default=None) )

解决方案 23:

如果您检查密钥的原因是为了确保您可以访问它们,那么一个选择就是不检查 - 只需尝试访问它们,然后在必要时执行必要的操作。

foo = {
    'bar': 4
}

try:
    alpha = foo['bar']
    beta = foo['leroy_jenkins']
except KeyError:
    pass # Or some other thing if you don't have the keys you expected.

解决方案 24:

根据我的测试Python 3.13.0,这是最快的版本:

>>> foo = {
...     'foo': 1,
...     'zip': 2,
...     'zam': 3,
...     'bar': 4
... }
... for k in ('foo', 'bar'):
...     if k not in foo:
...         contains = False
...         break
...     else:
...         contains = True
...         
>>> contains
True

@John La Rooy's使用答案来计时:

Python 3.13.0 (main, Nov  1 2024, 19:38:12) [Clang 16.0.0 (clang-1600.0.26.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from timeit import Timer
>>> setup='''from random import randint as R;d=dict((str(R(0,1000000)),R(0,1000000)) \nfor i in range(D));q=dict((str(R(0,1000000)),R(0,1000000)) for i in range(Q));print("\nlooking 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 632487
0.03017895808443427
>>> Timer('set(q) <= d.keys()','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632308
9.833136573433876e-06
>>> Timer('all(k in d for k in q)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632107
3.875000402331352e-06
>>> Timer('''
... for k in q:
...     if k not in d:
...         in_ = False
...         break
...     else:
...         in_ = True
... ''','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632327
2.3329630494117737e-06

解决方案 25:

>>> ok
{'five': '5', 'two': '2', 'one': '1'}

>>> if ('two' and 'one' and 'five') in ok:
...   print "cool"
... 
cool

这似乎有效

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用