Pyderman - 11 months ago 26

Python Question

Following on from this question, I now need to **sum** similar entries (tuples) within an overall tuple.

So given a tuple-of-tuples such as:

`T = (('a', 'b', 2),`

('a', 'c', 4),

('b', 'c', 1),

('a', 'b', 8),)

For all tuples where the

`(('a', 'b', 10),`

('a', 'c', 4),

('b', 'c', 1),)

The order of the tuples within the enclosing tuple (and the summing) doesn't matter.

We are dealing with tuples so we can't take advantage of something like

`dict.get()`

`defaultdict`

`In [1218]: d = defaultdict(lambda: defaultdict(int))`

In [1220]: for t in T:

d[t[0]][t[1]] += t[2]

......:

In [1225]: d

Out[1225]:

defaultdict(<function __main__.<lambda>>,

{'a': defaultdict(int, {'b': 10, 'c': 4}),

'b': defaultdict(int, {'c': 1})})

I'm not quite sure how to reconstruct that into a tuple-of-tuples. Any anyway, although the order of the three elements within each tuple will be consistent, I'm not comfortable with my indexing of the tuples. Can this be done without any conversion to other data types?

Answer

Code -

```
from collections import defaultdict
T1 = (('a', 'b', 2),
('a', 'c', 4),
('b', 'c', 1),
('a', 'b', 8),)
d = defaultdict(int)
for x, y, z in T1:
d[(x, y)] += z
T2 = tuple([(*k, v) for k, v in d.items()])
print(T2)
```

Output -

```
(('a', 'c', 4), ('b', 'c', 1), ('a', 'b', 10))
```

If you're interested in maintaining the original order, then -

```
from collections import OrderedDict
T1 = (('a', 'b', 2), ('a', 'c', 4), ('b', 'c', 1), ('a', 'b', 8),)
d = OrderedDict()
for x, y, z in T1:
d[(x, y)] = d[(x, y)] + z if (x, y) in d else z
T2 = tuple((*k, v) for k, v in d.items())
print(T2)
```

Output -

```
(('a', 'b', 10), ('a', 'c', 4), ('b', 'c', 1))
```

In Python 2, you should use this -

```
T2 = tuple([(x, y, z) for (x, y), z in d.items()])
```