如何统计嵌套字典中的所有元素?
我该怎么高效地计算一个嵌套字典中的子元素数量呢?我发现len()函数的表现和我最开始想的不太一样:
>>> food_colors = {'fruit': {'orange': 'orange', 'apple': 'red', 'banana': 'yellow'}, 'vegetables': {'lettuce': 'green', 'beet': 'red', 'pumpkin': 'orange'}}
>>> len(food_colors)
2
>>>
如果我实际上想要计算子元素的数量(比如,期望的结果是“6”),有没有比逐个遍历每个元素并累加子元素数量更好的方法呢?在这个特定的应用中,我大约有五百万个子元素需要计算,每一次计算都很重要。
10 个回答
6
针对你的具体问题,你可以直接使用这个:
>>> d={'fruit':
{'orange': 'orange', 'apple': 'red', 'banana': 'yellow'},
'vegetables':
{'lettuce': 'green', 'beet': 'red', 'pumpkin': 'orange'}}
>>> len(d)
2 # that is 1 reference for 'fruit' and 1 for 'vegetables'
>>> len(d['fruit'])
3 # 3 fruits listed...
>>> len(d['vegetables'])
3 # you thought of three of those...
>>> len(d['fruit'])+len(d['vegetables'])
6
虽然你可以用Python的各种工具来计算这个简单字典里的元素数量,但更有趣和更有成效的做法是先考虑一下数据的结构。
Python的基本数据结构有列表、集合、元组和字典。这些数据结构都可以通过引用“包含”自己或者其他数据结构的嵌套版本。
这个列表就是一个嵌套列表:
>>> l = [1, [2, 3, [4]], [5, 6]]
>>> len(l)
3
>>> l[0]
1
>>> l[1]
[2, 3, [4]]
>>> l[2]
[5, 6]
第一个元素是整数1。元素1和2本身也是列表。其他基本的Python数据结构也可以这样嵌套。这些被称为递归数据结构。你可以用pprint来打印它们。
如果你能稍微整理一下你的字典,用Python最简单的工具提取信息就会容易得多:
>>> color='color'
>>> family='family'
>>> sensation='sensation'
>>> good_things={
'fruit':
{
'orange':
{
color: 'orange',
family: 'citrus',
sensation: 'juicy'
},
'apple':
{
color: ['red','green','yellow'],
family:'Rosaceae',
'sensation': 'woody'
},
'banana':
{
color: ['yellow', 'green'],
family: 'musa',
sensation: 'sweet'
}
},
'vegatables':
{
'beets':
{
color: ['red', 'yellow'],
family: 'Chenopodiaceae',
sensation: 'sweet'
},
'broccoli':
{
color: 'green',
family: 'kale',
sensation: 'The butter you put on it',
}
}
}
现在对这些数据的查询就更有意义了:
>>> len(good_things)
2 # 2 groups: fruits and vegetables
>>> len(good_things['fruit'])
3 # three fruits cataloged
>>> len(good_things['vegetables'])
2 # I can only think of two vegetables...
>>> print good_things['fruit']['apple']
{'color': ['red', 'green', 'yellow'], 'sensation': 'woody', 'family': 'Rosaceae'}
>>> len(good_things['fruit']['apple']['color'])
3 # apples have 3 colors
14
任意深度,一行代码:
def count(d):
return sum([count(v) if isinstance(v, dict) else 1 for v in d.values()])
20
每个顶层的键值是否保证是一个字典,并且没有第二层的键值是字典?如果是这样的话,这样的操作会快得让你满意:
sum(len(v) for v in food_colors.itervalues())
如果数据结构更复杂,那就需要更多的代码了。当然,我不知道有什么内置的方法可以用来深入遍历复杂的数据结构。