如何计算嵌套字典中的所有元素?

时间:2011-01-03 02:13:45

标签: python

如何以最有效的方式计算嵌套字典中的子元素数? len()函数不能像我最初预期的那样工作:

>>> food_colors = {'fruit': {'orange': 'orange', 'apple': 'red', 'banana': 'yellow'}, 'vegetables': {'lettuce': 'green', 'beet': 'red', 'pumpkin': 'orange'}}
>>> len(food_colors)
2
>>>

如果我真的想要计算子元素的数量怎么办? (例如,预期结果为“6”)是否有更好的方法来做到这一点而不是循环遍历每个元素并总结子元素的数量?在这个特定的应用程序中,我有大约500万个子元素需要计数,每个时钟周期都很重要。

10 个答案:

答案 0 :(得分:17)

是否保证每个顶级键都有一个字典作为其值,并且没有二级键具有字典?如果是这样,这将尽可能快地达到:

sum(len(v) for v in food_colors.itervalues())

如果数据结构更复杂,当然需要更多代码。我不知道进行深度数据结构漫步的任何内在函数。

答案 1 :(得分:5)

对于您的具体问题,您可以使用:

>>> 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的基本数据结构是lists, sets, tuples, and dictionaries。这些数据结构中的任何一个都可以通过引用“保存”其自身或其他数据结构的任何嵌套版本。

此列表是nested list

>>> 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数据结构都是如此。这些是recursive data structures。您可以使用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

答案 2 :(得分:5)

您可以使用递归函数执行此操作。

>>> x
{'a': 1, 'b': 2, 'c': 3, 'd': {'I': 1, 'II': 2, 'III': 3}, 'e': 5}
>>> def test(d):
...   cnt = 0
...   for e in d:
...     if type(d[e]) is dict:
...       cnt += test(d[e])
...     else:
...       cnt += 1
...   return cnt
...
>>> test(x)
7

答案 3 :(得分:1)

sum(len(x) for x in food_colors.values())

答案 4 :(得分:1)

你只想要直系孩子吗?如果是这样,这可能是最好的:

sum(len(x) for x in fc.values())

答案 5 :(得分:1)

子元素是不同的对象,没有其他关系可以使用,从根本上比迭代它们更快 - 尽管有很多方法可以做到这一点(使用map.values(),例如)性能会有所不同,您可能希望使用timeit来比较它们。

如果计算它们对您的应用程序很重要,请考虑做一些事情以使其更容易:

  • 在构建数据结构时计算它们
  • 而不是嵌套的dict,考虑使用sqlite的内存connect(":memory:")表(这可能会减慢其他操作,或者使它们更复杂,但需要权衡值得考虑。)

答案 6 :(得分:1)

c = sum([len(i) for i in fruit_colors.values() ])

答案 7 :(得分:1)

对于任意深度嵌套词典:

def num_elements(x):
  if isinstance(x, dict):
    return sum([num_elements(_x) for _x in x.values()])
  else: return 1

答案 8 :(得分:0)

任意深度,一个班轮:

def count(d):
    return sum([count(v) if isinstance(v, dict) else 1 for v in d.values()])

答案 9 :(得分:0)

我使用了不止一层的嵌套字典。 例如在你的例子中,如果 'apple': 'red', 而是'apples': {'granny smith': 'green', 'gala': 'red'}, 递归函数可以给你答案。对于多个级别,我发现您需要进行计数。如果我想计算每个元素,我会使用它。

def dcount(dct, ci=0):
    # count all items in dict tree (including heirarchy)
    ci = ci + len(dct)
    if isinstance(dct, dict):
        for k1, v1 in dct.items():
            # if the lowest level is list, use instead
            # if isinstance(v1, (dict, list, tuple)):
            if isinstance(v1, dict): 
                ci = dcount(v1, ci)
    return ci

或者,变体

def dcount(dct, ci=0):
    for k1, v1 in dct.items():
        ci += 1
        if isinstance(v1, dict):
            ci = dcount(v1, ci)
    return ci

>>>d = {1: 1, 2: 2, 3: {4: 4, 5: {6: 6, 7: 7, 8: 8}, 9: 9}, 10: 10}
>>>dcount(d)
>>>10