简体   繁体   中英

Summing elements of list of lists in Python

I have the following list of lists:

myList = [[8100, 3], [8200, 5], [8400, 8]]

I would like to sum the second element of every sub-list to the next second element of the next list and so on.

Here is how it should look:

myList = [[8100, 3], [8200, 5], [8400, 8]]
myNewList = [[8100, 3], [8200, 8], [8400, 16]]

Because 3+5=8, 8+8=16 and so on. Is there any method to do this? Or am i supposed to write my own function for that, using NumPy for example?

Use np.cumsum given your array is large or you wanna do further manipulations. For smaller ones custom python function would be better.

a = np.array(myList)
a[:, 1] = a[:, 1].cumsum()

Output

array([[8100,    3],
       [8200,    8],
       [8400,   16]])

You can achieve the results in one pass O(n) and without allocating any additional space O(1) , unless you want to, by looping from the first element, progressively updating the items to be summed as follows:

In [1]: A = [[8100, 3], [8200, 5], [8400, 8]]

In [2]: for i in range(1, len(A)):
            A[i][-1] += A[i-1][-1]

In [3]: A
Out[3]: [[8100, 3], [8200, 8], [8400, 16]]

this method should work:

myNewList = []
value = 0
for sublist in myList:
    value = sublist[1]+value
    newSublist = [sublist[0],value]
    myNewList.append(newSublist) 

so simply store the previous value in a temprary variable adn add that to the next sublists second element.

col1, col2 = zip(*myList)
# col1 == (8100, 8200, 8400), col2 == (3, 5, 8)
sums = [ sum(col2[:i]) for i, _ in enumerate(col2, 1) ]
# sums == [3, 8, 16]
myNewList = [ list(x) for x in zip(col1, sums) ]
# myNewList == [[8100, 3], [8200, 8], [8400, 16]]

A very simple way to solve this, is to maintain a total variable and replace the second value of each sub-list with this sum.

myList = [[8100, 3], [8200, 5], [8400, 8]]
total, new_list = 0, []

for sublist in myList:
    total += sublist[1]
    new_list.append([sublist[0],total])

print(new_list)

Output

[[8100, 3], [8200, 8], [8400, 16]]

You can use the new assignment operator (or walrus operator ) to create an accumulator inside a comprehension:

myList = [[8100, 3], [8200, 5], [8400, 8]]

acc=0
new_list=[[sl1, acc := acc + sl2] for sl1, sl2 in myList]
>>> new_list
[[8100, 3], [8200, 8], [8400, 16]]

This is only for Python 3.8+

I made an example for you as clear as possible: you can make the function drier and more efficient, if you think about merging the loops.

L = [[8100, 3], [8200, 5], [8400, 8]]

def newList(L):
    gen = []
    for subL in L:
        if len(gen) > 0:
            gen.append(gen[-1] + subL[1])
        else:
            gen.append(subL[1])

    for idx, subL in enumerate(L):
        subL[1] = gen[idx]

    print(L)

newList(L)

Output:

[[8100, 3], [8200, 8], [8400, 16]]

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