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 first and second element are identical , I want to sum the third element, otherwise, leave the tuple in place. So I will end up with the following tuple-of-tuples:
(('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()
. If we go the defaultdict
route :
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?
You just need a defaultdict(int)
:
>>> from collections import defaultdict
>>>
>>> d = defaultdict(int)
>>> T = (('a', 'b', 2),
... ('a', 'c', 4),
... ('b', 'c', 1),
... ('a', 'b', 8),)
>>>
>>> for key1, key2, value in T:
... d[(key1, key2)] += value
...
>>> [(key1, key2, value) for (key1, key2), value in d.items()]
[
('b', 'c', 1),
('a', 'b', 10),
('a', 'c', 4)
]
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()])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.