获取Python字典中所有键的数量

新手上路,请多包涵

我在 Python 2.7 中有一本字典。

我需要快速计算所有键的数量,包括每个词典中的键。

所以在这个例子中,我需要所有键的数量都是 6:

 dict_test = {'key2': {'key_in3': 'value', 'key_in4': 'value'}, 'key1': {'key_in2': 'value', 'key_in1': 'value'}}

我知道我可以使用 for 循环遍历每个键,但我正在寻找一种更快的方法来执行此操作,因为我将拥有数千/数百万个键并且这样做是无效的:

 count_the_keys = 0

for key in dict_test.keys():
    for key_inner in dict_test[key].keys():
       count_the_keys += 1

# something like this would be more effective
# of course .keys().keys() doesn't work
print len(dict_test.keys()) * len(dict_test.keys().keys())

原文由 Ivan Bilan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 778
2 个回答

保持简单

如果我们知道所有的值都是字典,并且不想检查它们的任何值也是字典,那么它就像这样简单:

 len(dict_test) + sum(len(v) for v in dict_test.itervalues())

稍微改进一下,在计算值之前实际检查值是否为字典:

 len(dict_test) + sum(len(v) for v in dict_test.itervalues() if isinstance(v, dict))

最后,如果你想做一个任意深度,像下面这样:

 def sum_keys(d):
    return (0 if not isinstance(d, dict)
            else len(d) + sum(sum_keys(v) for v in d.itervalues())

print sum_keys({'key2': {'key_in3': 'value', 'key_in4': 'value'},
                'key1': {'key_in2': 'value',
                         'key_in1': dict(a=2)}})
# => 7

在最后一种情况下,我们定义了一个将被递归调用的函数。给定一个值 d ,我们返回:

  • 0 如果该值不是字典;或者
  • 字典中的键数,加上我们所有孩子的键总数。

让它更快

以上是一种简洁易懂的方法。我们可以使用生成器更快一点:

 def _counter(d):
    # how many keys do we have?
    yield len(d)

    # stream the key counts of our children
    for v in d.itervalues():
        if isinstance(v, dict):
            for x in _counter(v):
                yield x

def count_faster(d):
    return sum(_counter(d))

这让我们获得了更多的性能:

 In [1]: %timeit sum_keys(dict_test)
100000 loops, best of 3: 4.12 µs per loop

In [2]: %timeit count_faster(dict_test)
100000 loops, best of 3: 3.29 µs per loop

原文由 donkopotamus 发布,翻译遵循 CC BY-SA 3.0 许可协议

作为更通用的方法,您可以使用递归函数和生成器表达式:

 >>> def count_keys(dict_test):
...     return sum(1+count_keys(v) if isinstance(v,dict) else 1 for _,v in dict_test.iteritems())
...

例子:

 >>> dict_test = {'a': {'c': '2', 'b': '1', 'e': {'f': {1: {5: 'a'}}}, 'd': '3'}}
>>>
>>> count(dict_test)
8

_注意_:在 python 3.X 中使用 dict.items() 方法而不是 iteritems()

具有公认答案的基准表明此功能比公认答案更快:

 from timeit import timeit

s1 = """
def sum_keys(d):
    return 0 if not isinstance(d, dict) else len(d) + sum(sum_keys(v) for v in d.itervalues())

sum_keys(dict_test)
"""

s2 = """
def count_keys(dict_test):
    return sum(1+count_keys(v) if isinstance(v,dict) else 1 for _,v in dict_test.iteritems())

count_keys(dict_test)
   """

print '1st: ', timeit(stmt=s1,
                      number=1000000,
                      setup="dict_test = {'a': {'c': '2', 'b': '1', 'e': {'f': {1: {5: 'a'}}}, 'd': '3'}}")
print '2nd : ', timeit(stmt=s2,
                       number=1000000,
                       setup="dict_test = {'a': {'c': '2', 'b': '1', 'e': {'f': {1: {5: 'a'}}}, 'd': '3'}}")

结果:

 1st:  4.65556812286
2nd :  4.09120802879

原文由 Mazdak 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题