1

I have a list of tuples as follows:

lst = [(1, 2, 3), (2, 4, 5), (3, 6, 7), (4, 8, 9)]

The list is generated pre-sorted in ascending order by the first element of each tuple and the tuples are always formed of 3 elements.

I'd like to return a list of the sum of each element after the first element in each tuple up to but not including a maximum first element value, say in this case; 4.

The sum of the second elements should be 2 + 4 + 6 = 12 and the sum of the third elements should be 3 + 5 + 7 = 15.

Worth me mentioning that in real life lst can contain thousands of tuples and the tuples contain hundreds of elements for which individual sums will need to be calculated.

I could do:

sum_lst = [sum(t[e] for t in lst if t[0] < 4) for e in range(1, len(lst[0]))]

But this would have to examine all the tuples in the list which isn't efficient given it's known where in the list the summing should stop.

To stop at 4 I could do:

def calc_sum_lst(lst, e):
    sum_lst = 0
    for t in lst:
        if t[0] == 4:
            return sum_lst
        else:
            sum_lst += t[e]

sum_lst = [calc_sum_lst(lst, e) for e in range(1, len(lst[0]))]

However I'm wondering if there's a solution that's quicker and more elegant than using for loops?

Worth me also mentioning that I found this similar post but the answers all use for loops.

Jossy
  • 589
  • 2
  • 12
  • 36

1 Answers1

1

You can break once you reach the maximum value, to stop iterating through the rest. You can also pre-populate a list with 0s, then add to the correct index of the index. You could either adjust the index by -1 as I've done below, or delete the 0 index item of the list afterwards.

lst = [(1, 2, 3), (2, 4, 5), (3, 6, 7), (4, 8, 9)]

stop_at_num = 4
sum_lst = [0] * (len(lst[0]) - 1)

for i in range(len(lst)):
    if lst[i][0] >= stop_at_num:
        break
    for e in range(1, len(lst[0])):
        sum_lst[e-1] += lst[i][e]

to get sum_lst

[12, 15]
Hammurabi
  • 1,141
  • 1
  • 4
  • 7