Jacob Myer
Jacob Myer

Reputation: 509

How do i sum the second element of a tuple within a list of lists?

I have a list of lists named allBins which contains several lists which represent different bins, inside those bins are varying numbers of tuples with the format (iD, volume). I need to iterate through to sum the volumes of the items in each of the bins by summing the second element of the tuples.

I've tried many things: sum(bin[1] for bin in allBins) gives me a 'list index out of range' error presumably because some bins have more than one tuple?

allBins = [[(3,20)],[(1,11),(0,6)],[(4,16),(2,5)]]

I need a line of code that, depending on which bin I choose to sum, gives me the following integers:

1st bin: 20

2nd bin: 17

3rd bin: 21

Upvotes: 2

Views: 1602

Answers (6)

Mykola Zotko
Mykola Zotko

Reputation: 17824

You can use the following function:

from operator import itemgetter

allBins = [[(3,20)],[(1,11),(0,6)],[(4,16),(2,5)]]

def func(bin_num, all_bins):
    bin = itemgetter(bin_num)(all_bins)
    s = sum(map(itemgetter(-1), bin))
    return s

print(func(2, allBins))
# 21

Upvotes: 0

munk
munk

Reputation: 12983

The problem you have is you want to only sum one bin, but you're trying to sum across all bins. This means when you access the first bin, with the value [(3,20)] and ask for element with index 1, there is only an element with index 0 and you get the out of bounds error.

You want something like this:

def sum_bin(bin_num, data):
    my_bin = data[bin_num]
    return sum(t[1] for t in my_bin)

>>> sum_bin(0, allBins)
20
>>> sum_bin(1, allBins)
17
>>> sum_bin(2, allBins)
21

as a "one liner", assuming you have a variable capturing the bin you want

sum(t[1] for t in allBins[bin_idx])

This is called a generator comprehension, and while it's similar to a list comprehension, there are subtle differences.

Upvotes: 2

Luca Giorgi
Luca Giorgi

Reputation: 1010

for c,b in enumerate(allBins):
    if c == bin_you_choose_to_sum:
        partial=0
        for t in b:
            partial+=t[1]
        print("Bin {}: {}".format(c, partial))

Upvotes: 0

Austin
Austin

Reputation: 26039

You can use a list-comprehension:

allBins = [[(3,20)],[(1,11),(0,6)],[(4,16),(2,5)]]

print([sum(y[1] for y in x) for x in allBins])
# [20, 17, 21]

Treating your actual requirement: "I need some sort of loop or comprehension that, depending on which bin I choose to sum":

allBins = [[(3,20)],[(1,11),(0,6)],[(4,16),(2,5)]]

bin_number = 2
print(sum(x[1] for x in allBins[bin_number-1]))
# 17

You can specify bin_number and the above finds sum for that particular bin.

Upvotes: 5

Mark
Mark

Reputation: 6404

Once iterating over the main list, you can use sum to add up the integers.

allBins = [[(3,20)],[(1,11),(0,6)],[(4,16),(2,5)]]

def sumup(which, allBins):
    return sum(tup[1] for tup in allBins[which])

print(sumup(1, allBins))

Doc: sum built-in

Upvotes: 2

Raymond Hettinger
Raymond Hettinger

Reputation: 226316

You were close :-) Just put the summing fragment you gave inside a list comprehension so that it runs one summation per bin.

FWIW, you can also use operator.itemgetter() for a beautiful, functional approach:

>>> from operator import itemgetter

>>> allBins = [[(3,20)],[(1,11),(0,6)],[(4,16),(2,5)]]
>>> [sum(map(itemgetter(1), bin)) for bin in allBins]
[20, 17, 21]

Read this as, "make a list of sums for every bin in all bins" where the sums are "sum of item one in each tuple in a bin".

Upvotes: 2

Related Questions