获取Python字典字典中所有键的数量
我有一个Python 2.7词典的字典。
我需要快速计算所有键的数量,包括每个词典中的键。
所以在这个例子中,我需要所有的键的数量是6:
dict_test = {'key2': {'key_in3': 'value', 'key_in4': 'value'}, 'key1': {'key_in2': 'value', 'key_in1': 'value'}}
我知道我可以迭代循环中的每个键,但我正在寻找一个更快的方法来做到这一点,因为我将有成千上万的键,这样做是无效的:
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())
保持简单
如果我们知道所有的价值都是字典,而且不想检查它们的任何价值是否也是字典,那么它就像下面这样简单:
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
在最后一种情况下,我们定义一个recursion调用的函数。 给定值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
怎么样
n = sum([len(v)+1 for k, v in dict_test.items()])
你正在做的是遍历所有的键k和值v。值是你的子句。 您将获得这些字典的长度并添加一个包含用于索引子字典的键。
之后,你总结列表获得完整的密钥数量。
编辑:
为了澄清,这个片段只适用于字典字典的问题。 不是词典字典的字典…
所以不要用它嵌套的例子:)
作为更一般的方法,您可以使用recursion函数和生成器expression式:
>>> 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
在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
就像是:
print len(dict_test) + sum(len(v) for v in dict_test.values())
这里是recursion函数来查找嵌套字典的键的总数量…
s=0 def recurse(v): if type(v)==type({}): for k in v.keys(): global s s+=1 recurse(v[k])
你可以尝试使用pandasDataFrame的:
>>> 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×Mmatrix,其中N是“父”键的数量,M是唯一的子键的数量:
1 4 7 2 a NaN NaN 3 b NaN NaN 5 NaN cx 6 NaN d NaN
对于每个[行,列]你有一个值或NaN。 你只需要计算非NaN
值,这将给你的子键的数量,并添加len(df.columns)
,即列的数量(即父键)。
recursion函数:
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
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])
但我倾向于认为这是相当难以理解的。
尝试这个,
l = len(dict_test) for k in dict_test: l += len(dict_test[k])