CosmoSurreal
CosmoSurreal

Reputation: 259

Comparing rows elements in python

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

Answers (2)

Jon Clements
Jon Clements

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

eumiro
eumiro

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

Related Questions