在python中使用map处理列表时获取项目索引


78

使用map()处理列表时,我想在lambda内访问该项目的索引。我怎样才能做到这一点?

例如

ranked_users = ['jon','bob','jane','alice','chris']
user_details = map(lambda x: {'name':x, 'rank':?}, ranked_users)

在上面的示例中,如何获取每个用户的排名?

Answers:


110

使用枚举

In [3]: user_details = [{'name':x, 'rank':i} for i,x in enumerate(ranked_users)] 

In [4]: user_details
Out[4]: 
[{'name': 'jon', 'rank': 0},
 {'name': 'bob', 'rank': 1},
 {'name': 'jane', 'rank': 2},
 {'name': 'alice', 'rank': 3},
 {'name': 'chris', 'rank': 4}]

PS。我的第一个答案是

user_details = map(lambda (i,x): {'name':x, 'rank':i}, enumerate(ranked_users))

我强烈建议使用列表理解或发电机表达过maplambda只要有可能。列表理解更具可读性,并且往往更快地启动。


2
lambda的参数不应该没有括号吗?
dreerosaur 2011年

1
@dheerosaur在这种情况下不可以,因为对enumerate的next()操作返回一个元组。此lambda等效于def foo((i,x))
Rod

1
@dererosaur:实际上,括号是必需的。enumerate生成元组(单个对象)。
unutbu 2011年

@ Rod,@ unutbu:知道了。因此,lambdas不能像列表推导那样解压元组。
dreerosaur 2011年

3
@dheerosaur:是的,lambda的解压缩与列表解析的解压缩不同(在Python2中)。请注意,在Python3中,lambdas根本拒绝解包:请参见diveintopython3.org/…
unutbu 2011年

8

或者,您可以使用列表推导而不是map()和lambda。

ranked_users = ['jon','bob','jane','alice','chris']
user_details = [{'name' : x, 'rank' : ranked_users.index(x)} for x in ranked_users]

输出:

[{'name': 'jon', 'rank': 0}, {'name': 'bob', 'rank': 1}, {'name': 'jane', 'rank': 2}, {'name': 'alice', 'rank': 3}, {'name': 'chris', 'rank': 4}]

List内涵是非常强大的,也比的组合maplambda


8
list.index() 仅在以下情况下才适用: ranked_users都是唯一的。给定ranked_users = ['chris','chris'] user_details输出[{'name': 'chris', 'rank': 0}, {'name': 'chris', 'rank': 0}]应在的位置[{'name': 'chris', 'rank': 0}, {'name': 'chris', 'rank': 1}]
thisgeek 2012年

(鉴于此数据)对于成员来说唯一的是
有意义的

当然。您的答案符合示例。我只是认为为所有遇到此问题的人声明唯一性警告是个好主意。
thisgeek 2012年

在ranked_users列表上使用索引功能调用有点过分设计。用于表达的Python遍历数据结构中的对象
cheshire cat

6

在我看来,问题在于地图功能,而首选答案是部分正确的,这是由于将元组参数放入lambda导致语法错误 lambda (i,x)

枚举的想法很好,正确的解决方案是:

map(lambda x: {'name':x[1], 'rank':x[0]}, enumerate(ranked_users))

以及一些比较速度和理解力的时间:

def with_map():
    ranked_users = range(10 ** 6)
    list(map(lambda x: {'name': x[1], 'rank': x[0]}, enumerate(ranked_users)))

def by_comprehension():
    ranked_users = range(10 ** 6)
    [{'name': x, 'rank': i} for i, x in enumerate(ranked_users)]

from timeit import timeit
time_with_map = timeit(with_map, number=10)
time_with_comprehension = timeit(by_comprehension, number=10)

print('list comprehension is about %.2f x faster than map in this test case' % (time_with_map/time_with_comprehension))

测试结果:在此测试案例中,列表理解比map快约1.31倍


2

实际上,与在地图中使用枚举元组相比,这是一个更优雅,更冗长的解决方案(由于元组索引)。Map可以将更多的Iterables作为参数,因此让我们使用它。

map(lambda user, user_id: (user_id, user), ranked_users, range(ranked_users.__len__()))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.