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

时间:2016-02-16 08:50:37

标签: python python-2.7 dictionary

我在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())

10 个答案:

答案 0 :(得分:30)

保持简单

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

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

答案 1 :(得分:9)

怎么样

n = sum([len(v)+1 for k, v in dict_test.items()])

你正在做的是迭代所有键k和值v。值v是你的子词。您将获得这些词典的长度并添加一个以包含用于索引子词典的键。

之后,您对列表求和以获得完整的密钥数。

编辑:

为了澄清,此代码段仅适用于所要求的字典词典。不是字典词典的词典...
所以不要将它用于嵌套示例:)

答案 2 :(得分:9)

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

>>> 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

答案 3 :(得分:6)

使用Python 3.x中的生成器函数和yield from语法。这适用于任意嵌套字典

>>> from collections import Mapping
>>> def count_keys(mydict):
...     for key, value in mydict.items():
...         if isinstance(value, Mapping):
...             yield from count_keys(value)
...     yield len(mydict)
... 
>>> dict_test = {'key2': {'key_in3': 'value', 'key_in4': 'value'}, 'key1': {'key_in2': 'value', 'key_in1': 'value'}}
>>> sum(count_keys(dict_test))
6

在Python 2.x中你需要这样做:

>>> def count_keys(mydict):
...     for key, value in mydict.items():
...         if isinstance(value, Mapping):
...             for item in count_keys(value):
...                 yield 1
...         yield 1
... 
>>> sum(count_keys(dict_test))
6

答案 4 :(得分:5)

类似的东西:

print len(dict_test) + sum(len(v) for v in dict_test.values())

答案 5 :(得分:5)

这是查找嵌套字典的递归函数。钥匙总数......

s=0
def recurse(v):
   if type(v)==type({}):
     for k in v.keys():
      global s
      s+=1
      recurse(v[k])

答案 6 :(得分:4)

您可以尝试使用pandas DataFrame:

>>> import pandas as pd
>>> data = {'1': {'2': 'a', '3': 'b'}, '4': {'5': 'c', '6': 'd'}, '7': {'5': 'x'}}
>>> df = pd.DataFrame(data)
>>> print (df.count().sum() + len(df.columns))  # 8

pd.DataFrame(data)行会将您的字典转换为N x M矩阵,其中N是" parent" keys和M是唯一子键的数量:

     1    4    7
2    a  NaN  NaN
3    b  NaN  NaN
5  NaN    c    x
6  NaN    d  NaN

对于每个[行,列],您有一个值或NaN。您只需要计算非NaN值,它将为您提供子键数并添加len(df.columns),它代表列数(即父键)。

答案 7 :(得分:4)

递归函数:

def count_keys(some_dict):
    count = 0
    for key in some_dict:
        if isinstance(some_dict[key], dict):
            count += count_keys(some_dict[key])
        count += 1
    return count

答案 8 :(得分:4)

len(dict)将返回字典中的键数,因此,假设您知道它是如何嵌套的,并且所有值都是字典:

counter = len(outer_dict)
for v in outer_dict.values :
    counter += len(v)

您可以将其包含在列表解析中:

counter = len(outer_dict)
counter += sum([len(inner_dict) for inner_dict in outer_dict.values])

这可能是最pythonic。您可以将其扩展为:

counter = len(outer_dict)
counter += sum([len(inner_dict) if isinstance(inner_dict, dict) else 0 for inner_dict in outer_dict.values])

但我倾向于认为这是相当难以理解的。

答案 9 :(得分:3)

试试这个,

l = len(dict_test)
for k in dict_test:
    l += len(dict_test[k])