python:在字典中存在检查多个键的最佳方法是什么?

时间:2013-04-14 21:34:46

标签: python dictionary

我的字典看起来像

d = {
  'name': 'name',
  'date': 'date',
  'amount': 'amount',
  ...
}

我想测试nameamount是否存在,所以我会做

if not `name` in d and not `amount` in d:
  raise ValueError # for example

假设我从api获取数据,并且我想测试字典中是否存在10字段。

它仍然是最好的寻找方式吗?

5 个答案:

答案 0 :(得分:34)

您可以使用set个交叉点:

if not d.viewkeys() & {'amount', 'name'}:
    raise ValueError

在Python 3中,那就是:

if not d.keys() & {'amount', 'name'}:
    raise ValueError

因为.keys()默认返回dict视图。 .viewkeys()(例如Python 3中的.keys()返回的Dictionary view objects充当集合,交集测试非常有效。

Python 2.7中的演示:

>>> d = {
...   'name': 'name',
...   'date': 'date',
...   'amount': 'amount',
... }
>>> not d.viewkeys() & {'amount', 'name'}
False
>>> del d['name']
>>> not d.viewkeys() & {'amount', 'name'}
False
>>> del d['amount']
>>> not d.viewkeys() & {'amount', 'name'}
True

请注意,仅当缺少两个键时,此测试才会为True。如果在缺少的情况下需要通过测试,请使用:

if not d.viewkeys() >= {'amount', 'name'}:
    raise ValueError

仅当两个键都存在时才为False:

>>> d = {
...   'name': 'name',
...   'date': 'date',
...   'amount': 'amount',
... }
>>> not d.viewkeys() >= {'amount', 'name'}
False
>>> del d['amount']
>>> not d.viewkeys() >= {'amount', 'name'})
True

对于严格比较(仅允许 两个键,不多也不少),在Python 2中,将字典视图与集合进行比较:

if d.viewkeys() != {'amount', 'name'}:
    raise ValueError

(因此在Python 3中将是if d.keys() != {'amount', 'name'})。

答案 1 :(得分:9)

if all(k not in d for k in ('name', 'amount')):
    raise ValueError

if all(k in d for k in ('name', 'amount')):
    # do stuff

答案 2 :(得分:3)

你也可以使用set as:

>>> d = {
  'name': 'name',
  'date': 'date',
  'amount': 'amount',
}
>>> test = set(['name','date'])
>>> test.issubset(set(d.keys()))
True

答案 3 :(得分:0)

我喜欢这种形式:

>>> d = {
...   'name': 'name',
...   'date': 'date',
...   'amount': 'amount'
... }
>>> tests={'name','date'}
>>> if any(test not in d for test in tests):
...    raise ValueError
>>> # no error...

>>> del d['name']
>>> if any(test not in d for test in tests):
...    raise ValueError
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError

适用于Py 2或Py 3

答案 4 :(得分:0)

为获得最大效率,您要避免构造不必要的临时set(所有非比较二进制运算符都需要)。您可以这样做:

if name not in d and amount not in d:

具有:

if d.keys().isdisjoint(("amount", "name")):

,但这可能是错误的逻辑(在两种情况下),因为当缺少两个键时,它仅进入if正文(并引发异常),并且您可能想如果缺少 键,则会引发异常。

有关拒绝d(除非它同时包含两个键)的更可能的预期逻辑,您需要这样做:

if name not in d or amount not in d:

这可以通过以下方式通过设置操作来完成:

首先,您要预先定义(在函数外部,以避免重复构建集合):

required_keys = frozenset({"amount", "name"})

然后做:

if not d.keys() >= required_keys:

两个解决方案(isdisjoint>=)都避免构造每个测试临时集,并且应尽可能高效地运行(一旦发现单个键丢失,则将其短路,并且仅两个键同时出现时,需要一对O(1)查找)。就个人而言,对于两个键,我会坚持使用if name not in d or amount not in d:,但是,如果键的数量增加,请确保使用类似集合的操作。