Deepak Gurumoorthy
Deepak Gurumoorthy

Reputation: 83

map with a lambda function that accepts two parameters

I would like to fetch i'th element from all the sub lists in a list of lists.I tried using map and lambda function as below

extract = lambda x,i :x[i]
a = [[1,2,3],[4,5,6],[6,7,8]]
b = list(map(extract(i = 1),a))

I expect b to be [2,5,7] but I know the last line doesn't work. How should I approach this with map and lambda

Upvotes: 2

Views: 324

Answers (5)

Niladri Basu
Niladri Basu

Reputation: 10614

You do not need to hard code the index.

IMHO, you should return a lambda function from extract method by doing something like this perhaps:

def extract(i):
    return lambda x : x[i]

a = [[1,2,3],[4,5,6],[6,7,8]]

b = list(map(extract(1), a))

print(b)          

Output:

[2, 5, 7]      

Note: Better(read pythonic) approach will be to use list comprehension like this:

a = [[1,2,3],[4,5,6],[6,7,8]]

b = [li[1] for li in a]

print(b)

Upvotes: 1

Dmitrii Eliuseev
Dmitrii Eliuseev

Reputation: 54

I also vote for the 'for' solution. Functional programming syntax looks beautiful but its too much overhead sometimes.

a = [[1,2,3],[4,5,6],[6,7,8]]
b = list(map(lambda x: x[1], a)) #  Brr, how many types conversions involved
c = [x[1] for x in a] # Looks more lightweight

Lets just check:

import timeit
timeit.timeit('a = [[1,2,3],[4,5,6],[6,7,8]]; b = [x[1] for x in a]', number=10000)
> 0.01244497299194336
timeit.timeit('a = [[1,2,3],[4,5,6],[6,7,8]]; b = list(map(lambda x: x[1], a))', number=10000)
> 0.021031856536865234

2 times slower.

Upvotes: 0

RoadRunner
RoadRunner

Reputation: 26315

I would suggest using operator.itemgetter here to fetch the second item of each sublist:

from operator import itemgetter

a = [[1,2,3],[4,5,6],[6,7,8]]

print(list(map(itemgetter(1), a)))
# [2, 5, 7]

Or using lambda:

a = [[1,2,3],[4,5,6],[6,7,8]]

print(list(map(lambda x: x[1], a)))
# [2, 5, 7]

Your anonymous function:

extract = lambda x,i :x[i]

Needs to instead map specifically an index:

extract = lambda x: x[1]

Then you can simply map this function to your list with map(extract(1), a).

Upvotes: 1

jpp
jpp

Reputation: 164693

The underlying problem is your first function argument needs to be specified when you call extract. This is possible via functools.partial:

from functools import partial
b = list(map(partial(extract, i=1), a))  # [2, 5, 7]

But this is relatively inefficient, since a new function is created for each iteration of a. Instead, as others have advised, use operator.itemgetter:

from operator import itemgetter
b = list(map(itemgetter(1), a))          # [2, 5, 7]

As an aside, PEP 8 advises against naming lambda functions; define explicitly instead:

def extract(x, i):
    return x[i]

Upvotes: 2

iz_
iz_

Reputation: 16603

You can hard code in the 1:

extract = lambda x: x[1]
a = [[1,2,3],[4,5,6],[6,7,8]]
b = list(map(extract,a))

print(b)
# [2, 5, 7]

You normally don't want to store a lambda to a variable, this is better:

def extract(x):
    return x[1]

b = list(map(extract, a))

Or simply this:

b = list(map(lambda x: x[1], a))

You can also use a list comprehension, which I personally think is the best option:

c = [x[1] for x in a]

print(b == c)
True

Upvotes: 2

Related Questions