iva*_*lan 38 python dictionary python-2.7
我在Python 2.7中有一本词典字典.
我需要快速计算所有键的数量,包括每个词典中的键.
所以在这个例子中,我需要所有键的数量为6:
dict_test = {'key2': {'key_in3': 'value', 'key_in4': 'value'}, 'key1': {'key_in2': 'value', 'key_in1': 'value'}}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用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())
Run Code Online (Sandbox Code Playgroud)
don*_*mus 30
保持简单
如果我们知道所有值都是字典,并且不希望检查它们的任何值也是字典,那么它就像下面这样简单:
len(dict_test) + sum(len(v) for v in dict_test.itervalues())
Run Code Online (Sandbox Code Playgroud)
稍微改进一下,在计算它们之前实际检查值是否为字典:
len(dict_test) + sum(len(v) for v in dict_test.itervalues() if isinstance(v, dict))
Run Code Online (Sandbox Code Playgroud)
最后,如果你想做任意深度,如下所示:
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
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,我们定义了一个将被递归调用的函数.给定一个值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))
Run Code Online (Sandbox Code Playgroud)
这让我们获得了更多的表现:
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
Run Code Online (Sandbox Code Playgroud)
怎么样
n = sum([len(v)+1 for k, v in dict_test.items()])
Run Code Online (Sandbox Code Playgroud)
你正在做的是迭代所有键k和值v.值v是你的子词.您获取这些词典的长度并添加一个以包含用于索引子词典的键.
然后,您对列表求和以获得完整的键数.
编辑:
为了澄清,这个片段仅适用于所要求的字典词典.不是字典词典的字典......
所以不要将它用于嵌套示例:)
作为一种更通用的方法,您可以使用递归函数和生成器表达式:
>>> def count_keys(dict_test):
... return sum(1+count_keys(v) if isinstance(v,dict) else 1 for _,v in dict_test.iteritems())
...
Run Code Online (Sandbox Code Playgroud)
例:
>>> dict_test = {'a': {'c': '2', 'b': '1', 'e': {'f': {1: {5: 'a'}}}, 'd': '3'}}
>>>
>>> count(dict_test)
8
Run Code Online (Sandbox Code Playgroud)
注意:在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'}}")
Run Code Online (Sandbox Code Playgroud)
结果:
1st: 4.65556812286
2nd : 4.09120802879
Run Code Online (Sandbox Code Playgroud)
使用生成器函数和yield fromPython 3.x中的新语法.这适用于任意嵌套字典
>>> 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
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
就像是:
print len(dict_test) + sum(len(v) for v in dict_test.values())
这是用于查找嵌套字典的键总数的递归函数...
s=0
def recurse(v):
if type(v)==type({}):
for k in v.keys():
global s
s+=1
recurse(v[k])
Run Code Online (Sandbox Code Playgroud)