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