Python Collections Counter for a List of Dictionaries

前端 未结 2 1145
时光取名叫无心
时光取名叫无心 2021-01-18 16:59

I have a dynamically growing list of arrays that I would like to add like values together. Here\'s an example:

{\"something\" : [{\"one\":\"200\"}, {\"three\         


        
相关标签:
2条回答
  • 2021-01-18 17:26

    I think this does what you want, but I'm not sure because I don't know what "The dict is also being dynamically created, so I can't build the list without the dicts" means. Still:

    input = {
        "something" : [{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"}], 
        "foo" : [{"a" : 100, "b" : 200}, {"a" : 300, "b": 400}],
    }
    
    def counterize(x):
        return Counter({k : int(v) for k, v in x.iteritems()})
    
    counts = {
        k : sum((counterize(x) for x in v), Counter()) 
        for k, v in input.iteritems()
    }
    

    Result:

    {
        'foo': Counter({'b': 600, 'a': 400}), 
        'something': Counter({'two': 800, 'three': 400, 'one': 300})
    }
    

    I expect using sum with Counter is inefficient (in the same way that using sum with strings is so inefficient that Guido banned it), but I might be wrong. Anyway, if you have performance problems, you could write a function that creates a Counter and repeatedly calls += or update on it:

    def makeints(x):
        return {k : int(v) for k, v in x.iteritems()}
    
    def total(seq):
        result = Counter()
        for s in seq:
            result.update(s)
        return result
    
    counts = {k : total(makeints(x) for x in v) for k, v in input.iteritems()}
    
    0 讨论(0)
  • 2021-01-18 17:29

    One way would be do as follows:

    from collections import defaultdict
    
    d = {"something" :
         [{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"}]}
    
    dd = defaultdict(list)
    
    # first get and group values from the original data structure
    # and change strings to ints
    for inner_dict in d['something']:
        for k,v in inner_dict.items():
            dd[k].append(int(v))
    
    
    # second. create output dictionary by summing grouped elemetns
    # from the first step.
    out_dict =  {k:sum(v) for k,v in dd.items()}
    
    print(out_dict)
    # {'two': 800, 'one': 300, 'three': 400}
    

    In here I don't use counter, but defaultdict. Its a two step approach.

    0 讨论(0)
提交回复
热议问题