37

Let's assume there is a list a = [1, 3, 5, 6, 8].

I want to apply some transformation on that list and I want to avoid doing it sequentially, so something like map(someTransformationFunction, a) would normally do the trick, but what if the transformation needs to have knowledge of the index of each object?

For example let's say that each element must be multiplied by its position. So the list should be transformed to a = [0, 3, 10, 18, 32].

Is there a way to do that?

LetsPlayYahtzee
  • 7,161
  • 12
  • 41
  • 65

6 Answers6

61

Use the enumerate() function to add indices:

map(function, enumerate(a))

Your function will be passed a tuple, with (index, value). In Python 2, you can specify that Python unpack the tuple for you in the function signature:

map(lambda (i, el): i * el, enumerate(a))

Note the (i, el) tuple in the lambda argument specification. You can do the same in a def statement:

def mapfunction((i, el)):
    return i * el

map(mapfunction, enumerate(a))

To make way for other function signature features such as annotations, tuple unpacking in function arguments has been removed from Python 3.

Demo:

>>> a = [1, 3, 5, 6, 8]
>>> def mapfunction((i, el)):
...     return i * el
...
>>> map(lambda (i, el): i * el, enumerate(a))
[0, 3, 10, 18, 32]
>>> map(mapfunction, enumerate(a))
[0, 3, 10, 18, 32]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    +1 for highlighting the trick with tuple assignment in a function definition. I have never seen that before. – Matt Hall Feb 18 '16 at 12:34
  • So that example applies only to python2? – LetsPlayYahtzee Feb 18 '16 at 13:16
  • 8
    @LetsPlayYahtzee: Yes, in Python 3, use one argument (which will be a tuple); `lambda i_el: i_el[0] * i_el[1]`; in a `def` statement you can unpack that on a separate line; `def mapfunction(i_el):`, *newline-and-indent-more*, `i, el = i_el`, *newline, match indent*, `return i * el`. – Martijn Pieters Feb 18 '16 at 13:18
12

You can use enumerate():

a = [1, 3, 5, 6, 8]

answer = map(lambda (idx, value): idx*value, enumerate(a))
print(answer)

Output

[0, 3, 10, 18, 32]
gtlambert
  • 11,711
  • 2
  • 30
  • 48
7

To extend Martijn Pieters' excellent answer, you could also use list comprehensions in combination with enumerate:

>>> a = [1, 3, 5, 6, 8]
>>> [i * v for i, v in enumerate(a)]
[0, 3, 10, 18, 32]

or

[mapfunction(i, v) for i, v in enumerate(a)]

I feel list comprehensions are often more readable than map/lambda constructs. When using a named mapping function that accepts the (i, v) tuple directly, map probably wins though.

marcelm
  • 1,032
  • 11
  • 11
  • you are right, in the later case the `map` notation makes more sense. In my case using a named function with map was the right choice, since practically the function had to do a little more than just multiplying by the index. – LetsPlayYahtzee Feb 18 '16 at 14:59
3

To make compatible with Python3

def map_fn(data):
    idx, el = data
    return idx*el

my_list = [2,3,5,7]

print(list(map(map_fn, list(enumerate(my_list)))))
Uno
  • 61
  • 3
1
# Python3
map(lambda args: print(args[0],args[1]) ,enumerate(a_list))
# use arg list, just get the result with index

# Python2
map(lambda index,content: print(index,content) ,enumerate(a_list))
Benchur Wong
  • 2,377
  • 2
  • 9
  • 13
0

Just a heads up that in python 3 the enumerate is not how it's written anymore

https://stackoverflow.com/a/15712231/1984636

sivi
  • 10,654
  • 2
  • 52
  • 51