0

How can I take a list of dicts like this:

ps = [{'one': {'a': 30,
               "b": 30},
       'two': {'a': -1000}},
      {'three': {'a': 44}, 'one': {'a': -225}},
      {'one': {'a': 2000,
               "b": 30}}]

and produce a dict of dicts like this:

{"one": {"a": 1805, "b": 60}, "two": {"a": -1000}, "three": {"a": 44}}

I'm pretty sure I can use a collections.Counter() to do this, but what I have so far doesn't work. it just returns whatever the last value of a or b was for each element:

res = Counter(ps[0])
for t in ps[1:]:
    for key, vals in t.items():
        res.update(vals)
        if key not in res.keys():
            res[key] = vals
        else:
            res[key].update(vals)

# Wrong!
res
Counter({'one': {'a': 2000, 'b': 30}, 'two': {'a': -1000}, 'a': 1819, 'b': 30})

I'm new to python so excuse what I'm sure is ugly code.

Alex
  • 1,997
  • 1
  • 15
  • 32
  • I'm not sure this is a duplicate. The additional level of nesting needs to be taken into account. I got around it using `defaultdict`: `res = defaultdict(Counter); for d in ps: for k, v in d.items(): d[k].update(v)` – Patrick Haugh Apr 20 '18 at 01:44
  • You can do `def red(x,y): ... keys = set(x).union(set(y)) ... return { k: {j: x.get(k, {}).get(j,0) + y.get(k, {}).get(j,0) for j in (x.get(k,{}).keys()+y.get(k,{}).keys())} for k in keys` and `reduce(red, ps)` – rafaelc Apr 20 '18 at 01:47

1 Answers1

0
res = {}
for t in ps: 
    for key, vals in t.items():
        if key not in res:
            res[key] = vals
        else:
            for innerKey, innerVal in vals.items():
                if innerKey not in res[key]:
                    res[key][innerKey] = 0 
                res[key][innerKey] += innerVal

And res is

{'three': {'a': 44}, 'two': {'a': -1000}, 'one': {'a': 1805, 'b': 60}}
greedy52
  • 1,345
  • 9
  • 8