7

The heading may sound bizarre but here is what I mean:

def f(x, y, z):
    return a_single_number_from_xyz
l = [(10, 'abc', 'def'), (20, 'efg', 'hij')]
print sum([ret_value_of_f_from_first_tuple, ret_value_of_f_from_second_tuple])

The three arguments of function f is the three elements of each of the tuple. Now, I want to apply function f to every tuple of list l and want to get the sum of those single numbers. How do I do that in a single statement? How do I map function and use list comprehension together here?

QuestionEverything
  • 4,809
  • 7
  • 42
  • 61

4 Answers4

11

In this particular case, I think you just want:

sum(n for n,_,_ in l)

But in general, you are looking for itertools.starmap, so

list(itertools.starmap(f, iterable)) 

is equivalent to

[f(*xs) for xs in iterable]

Hence the "star" map. Normally, I would just do:

sum(f(*xs) for xs in iterable)

For the general case, although:

sum(itertools.starmap(f, iterable))

Is similarly elegant to me.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
6

First let's make that an actual working function using all values, for example:

>>> def f(x, y, z):
        return x + len(y) + len(z)

Now your example data:

>>> l = [(10, 'abc', 'def'), (20, 'efg', 'hij')]

And one way to do it, giving map three iterables (one for each "column"):

>>> sum(map(f, *zip(*l)))
42

Lol. Didn't see that coming.

Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107
  • yours and @juanpa.arrivillaga 's answer are both elegant and brilliant! however, i'm accepting his answer as it was posted moments earlier. – QuestionEverything Oct 31 '17 at 23:08
1

You can try this:

def f(*args):
    return sum(map(lambda x:x[0], args))

l = [(10, 'abc', 'def'), (20, 'efg', 'hij'), (30, "klm", "nop")]
print(f(*l))

Output:

60
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
1

If what you need is just the sum, you can get it with this one-line code:

s = sum(t[0] for t in l)

Output:

>>> l = [(10, 'abc', 'def'), (20, 'efg', 'hij')]
>>> s = sum(t[0] for t in l)
>>> s
30
ettanany
  • 19,038
  • 9
  • 47
  • 63