Reputation: 259
We have a list:
import numpy as np
A=[(2, 2, 0), (1, 5, 0), (6, 8, 0), (2, 2, 2) ]
ax=np.asarray([row[0] for row in A])
ay=np.asarray([row[1] for row in A])
az=np.asarray([row[2] for row in A])
print (ax,ay,az)
I would like to compare ax with ay and when i find equal pairs where ax==ay like (2, 2, 0) and (2, 2, 2) i keep the pair once but add the az values. So in our example the new wanted list B would be:
B=[(2, 2, 2), (1, 5, 0), (6, 8, 0)]
It would be nice to have some code that would be efficient with really huge lists too.
Upvotes: 1
Views: 1417
Reputation: 142126
If order is NOT important
from collections import defaultdict
dd = defaultdict(int)
for x, y, z in A:
dd[(x,y)] += z
res = [k + (v,) for k, v in dd.iteritems()]
# [(1, 5, 0), (6, 8, 0), (2, 2, 2)]
If order IS important
from operator import itemgetter
d = {}
for idx, (x, y, z) in enumerate(A):
pos, freq = d.get((x,y), (0,0))
d[(x,y)] = min(pos, idx), freq + z
res = sorted((k + (v[1],) for k, v in d.iteritems()), key=itemgetter(1, 1))
# [(2, 2, 2), (1, 5, 0), (6, 8, 0)]
Upvotes: 1
Reputation: 212835
A dictionary (or a collections.Counter) is faster to check for present items than a numpy array.
So if the output order is not important:
from collections import Counter
c = Counter()
A = [(2, 2, 0), (1, 5, 0), (6, 8, 0), (2, 2, 2) ]
for a in A:
c[a[:2]] += a[2]
B = [list(k) + [v] for k,v in c.iteritems()]
B
is now:
[[1, 5, 0], [6, 8, 0], [2, 2, 2]]
Upvotes: 2