简体   繁体   中英

Summing up elements from one list based on indices in another list

So here is what I am trying to achieve in Python:

  • I have a list "A" with unsorted and repeated indices.
  • I have a list "B" with some float values
  • Length A = Length B
  • I want list "C" with summed values of B based on the repeated indices in A in a sorted ascending manner.

Example:

A = [0, 1, 0, 3, 2, 1, 2]  # (indicates unsorted and repeated indices)
B = [25, 10, 15, 10, 5, 30, 50]  # (values to be summed)
C = [25+15, 10+30, 5+50, 15]  # (summed values in a sorted manner)

So far I know how to do the sorting bit with:

C = zip(*sorted(zip(A, B)))

Getting the result:

[(0, 0, 1, 1, 2, 2, 3), (15, 25, 10, 30, 5, 50, 10)] 

But I do not know how to do the sum.

What would be a good way to create list C?

Use zip() in combination with a dict :

A = [0 , 1 , 0 , 3 , 2 , 1 , 2] 
B = [25 , 10 , 15 , 10 , 5 , 30 , 50]

sums = {}
for key, value in zip(A,B):
    try:
        sums[key] += value
    except KeyError:
        sums[key] = value
print(sums)
# {0: 40, 1: 40, 2: 55, 3: 10}

And see a demo on ideone.com .

You could use groupby , if the order matters:

In [1]: A=[0 , 1 , 0 , 3 , 2 , 1 , 2]

In [2]: B=[25 , 10 , 15 , 10 , 5 , 30 , 50]

In [3]: from itertools import groupby

In [4]: from operator import itemgetter

In [5]: C = [sum(map(itemgetter(1), group))
   ...:      for key, group in groupby(sorted(zip(A, B)),
   ...:                                key=itemgetter(0))]

In [6]: C
Out[6]: [40, 40, 55, 10]

or defaultdict(float) , if it does not:

In [10]: from collections import defaultdict

In [11]: res = defaultdict(float)

In [12]: for k, v in zip(A, B):
    ...:     res[k] += v
    ...:     

In [13]: res
Out[13]: defaultdict(float, {0: 40.0, 1: 40.0, 2: 55.0, 3: 10.0})

Note that dict s in python are unordered (you are not to trust any CPython implementation details).

It is actually a bit unclear what you want, but if you want them to be indexed by whatever the number is, you shouldn't even use a list, but a Counter instead:

>>> from collections import Counter
>>> c = Counter()
>>> A = [0, 1, 0, 3, 2, 1, 2]
>>> B = [25, 10, 15, 10 , 5, 30, 50]
>>> for k, v in zip(A, B):
...     c[k] += v
...
>>> c
Counter({2: 55, 0: 40, 1: 40, 3: 10})
>>> c[0]
40

If you really want a list, you can use

>>> [i[1] for i in sorted(c.items())]

but then any missing key would cause the rest of the values show up upper, which might or might not be that what you wanted.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM