【问题标题】:Update list elements based on a second list as index基于第二个列表作为索引更新列表元素
【发布时间】:2014-04-30 18:56:01
【问题描述】:

一个不太难的问题,我希望来自 Python 初学者。

我有一个主列表 listA,我需要根据索引列表 listB 中的值将该列表中的项目清零。

因此,例如,给定:

listA = [10, 12, 3, 8, 9, 17, 3, 7, 2, 8]
listB = [1, 4, 8, 9]

我想要的输出是

listC = [10, 0, 3, 8, 0, 17, 3, 7, 0, 0]

这个问题 [1] 看起来很相似,但要求将元素删除,而不是更改。我不确定是否需要类似的方法,但如果需要,我不知道如何应用它。

[1]how to remove elements from one list if other list contain the indexes of the elements to be removed

【问题讨论】:

    标签: python list


    【解决方案1】:

    您可以使用list comprehensionenumerateconditional expression

    >>> listA = [10, 12, 3, 8, 9, 17, 3, 7, 2, 8]
    >>> listB = [1, 4, 8, 9]
    >>>
    >>> list(enumerate(listA))  # Just to demonstrate
    [(0, 10), (1, 12), (2, 3), (3, 8), (4, 9), (5, 17), (6, 3), (7, 7), (8, 2), (9, 8)]
    >>>
    >>> listC = [0 if x in listB else y for x,y in enumerate(listA)]
    >>> listC
    [10, 0, 3, 8, 0, 17, 3, 7, 0, 0]
    >>>
    

    【讨论】:

    • 非常感谢您的帮助。我很乐意接受这一点,因为它工作正常,但由于我只能接受一个回复,我决定选择 mhlester's,其中还包括另一种方法。
    【解决方案2】:

    作为列表理解:

    listC = [value if index not in listB else 0 for index, value in enumerate(listA)]
    

    使用set for listB 可以显着改善大型列表:

    setB = set(listB)
    listC = [value if index not in setB else 0 for index, value in enumerate(listA)]
    

    或者复制列表修改一下,这样更快更易读:

    listC = listA[:]
    for index in listB:
        listC[index] = 0
    

    【讨论】:

    • 我不太确定前者更快:它对每个索引和enumerate 调用进行慢速列表成员资格测试。第二种方法进行一次快速复制,然后只将所需数量的元素归零。
    • 嘿,你可能是对的。有趣的是,很容易陷入总是假设列表理解更好的陷阱
    • 感谢您的回复。在我的实际数据中,listA 有 100 万个项目,而 listB 有 1089 个。使用 %%timeit 第一种方法需要 27.5 秒,而第二种方法只有 13 毫秒。可以这样吗?看起来差别很大。
    • @MichaelMaggs:测试列表中的成员资格很慢,因为必须一个一个地扫描元素(如果没有找到元素,直到您扫描了整个列表)。如果您先使用setB = set(listB),然后使用not in setB 而不是not in listB,它应该会快得多。
    • 是的,这有很大的不同。它将列表理解的时间从 27.5 秒降低到 191 毫秒。尽管如此,对于处理大型列表,简单循环仍然会在速度上获胜。
    猜你喜欢
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多