Search code examples
pythonpython-3.xlistreducefunctools

functools reduce() gives TypeError: 'int' object is not subscriptable


I am having problem with functools.reduce(). It returns int object is not subscriptable

total_population = functools.reduce(lambda a, b: a[0] + b[0], mid_points)

variable 'mid_points' list of tuples: sample is given in picture below

But when I tried above line of code on:

li = [(1,"a"), (2,"b")]

it gives correct output i.e 3

Please help! what am I do?

sample of mid_points


Solution

  • The result of reduce needs to be a valid input to the reduction function; you reduction function expects a sequence with at least one element, but you're returning an int. Just change the code to:

    [total_population] = functools.reduce(lambda a, b: (a[0] + b[0],), mid_points)
    

    to add a layer of tuple wrapping so indexing continues to work, and the brackets at the end unpack the resulting single element tuple. This will break if mid_points is a single element, so if that's possible:

    total_population, *_ = functools.reduce(lambda a, b: (a[0] + b[0],), mid_points)
    

    is slightly safer, as it just captures any extra elements in the result into an ignored list.

    An alternative (thanks for reminding me @deceze) is to give reduce a starting value, so a is always an int, both on the first call and all subsequent calls:

    total_population = functools.reduce(lambda a, b: a + b[0], mid_points, 0)
    

    The final argument to reduce is the first a and all subsequent as are results of previous calls. Of course, this can also be simplified in a third way to avoid reduce entirely:

    from operator import itemgetter
    
    total_population = sum(map(itemgetter(0), mid_points))
    
    # Or without an import, but ever-so-slightly slower:
    total_population = sum(pt[0] for pt in mid_points)
    

    since really you just need to do two things; extract the first element of each input, and sum them.