【问题标题】:Getting index of item while processing a list using map in python在python中使用map处理列表时获取项目索引
【发布时间】:2011-07-22 21:51:34
【问题描述】:

在使用 map() 处理列表时,我想在 lambda 中访问项目的索引。我该怎么做?

例如

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

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

【问题讨论】:

    标签: python


    【解决方案1】:

    使用enumerate:

    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 上使用列表解析或生成器表达式。列表推导更具可读性,并且往往启动速度更快。

    【讨论】:

    • lambda的参数不应该没有括号吗?
    • @dheerosaur 在这种情况下不是,因为 enumerate 上的 next() 操作返回一个元组。这个 lambda 等效于 def foo((i,x))
    • @dheerosaur:实际上,括号是强制性的。 enumerate 生成元组(单个对象)。
    • @Rod,@unutbu:知道了。所以,lambdas 不能像列表推导那样解包元组。
    • @dheerosaur:是的,lambda 的解包方式与列表推导式不同(在 Python2 中)。请注意,在 Python3 中,lambda 完全拒绝解包:请参阅 diveintopython3.org/…
    【解决方案2】:

    您也可以使用 list comprehension 而不是 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}]
    

    列表推导非常强大,与maplambda 的组合相比,它也是faster

    【讨论】:

    • 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}]
    • 只有成员是唯一的才有意义(鉴于此数据)......
    • 当然。你的答案符合这个例子。我只是认为向看到这篇文章的任何人说明独特性警告是个好主意。
    • 在排名用户列表上使用索引函数调用有点过度设计。用于表达式的 Python 迭代数据结构中的对象
    【解决方案3】:

    在我看来,这个问题是关于 map 函数的,由于将元组参数放入 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 倍

    【讨论】:

      【解决方案4】:

      实际上这里是一个比在映射中使用枚举元组更优雅、更详细的解决方案(因为元组索引)。 Map 可以接受更多的迭代作为参数,所以让我们使用它。

      map(lambda user, user_id: (user_id, user), ranked_users, range(ranked_users.__len__()))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-15
        • 1970-01-01
        • 2013-04-29
        • 2019-01-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多