【问题标题】:In-place replacement of all occurrences of an element in a list in python [duplicate]就地替换python列表中所有出现的元素[重复]
【发布时间】:2014-08-03 19:30:30
【问题描述】:

假设我有一个列表:

myl = [1, 2, 3, 4, 5, 4, 4, 4, 6]

就地双重强调)用44替换所有出现的4的最有效和最简单的pythonic方法是什么?

我也很好奇为什么没有standard 这样做的方法(尤其是当strings 有一个not-in-place replace 方法时)?

【问题讨论】:

  • @FrerichRaabe 不是重复的。通常,类似问题的答案并不关注就地要求。
  • @FrerichRaabe -- 不完全是。这没有指定 in-place 约束。如果这里没有其他骗子,我会感到惊讶,但事实并非如此;-)
  • @mgilson:我引用的另一个问题也没有指定“异地”约束。从这个意义上说,它是一个超集。因此,问题的答案给出了就地和不合时宜的(嗯,不确定这是就地的好反面:) 答案。所以我想你是对的 - 它不是重复的,而是“相关的”。我撤回了投票。
  • @FrerichRaabe -- 绝对相关。那里没有争论:-)
  • @FrerichRaabe 我实际上认为this question here 可能是复制的好人选;事实上,我想在那里发布我的answer,但由于各种原因问题已经关闭。

标签: python list replace in-place


【解决方案1】:
myl[:] = [x if x != 4 else 44 for x in myl]

使用列表推导执行原地替换,然后如果您真的想更改原始列表,则将新值切片分配到原始列表中。

【讨论】:

  • 唯一的事情是我们必须构建一个新列表并用新列表替换旧列表。我的版本在这里可能很有效。必须timeit 并确认。
  • @thefourtheye 用生成器表达式替换列表推导可能会有所帮助。
  • @bereal 请告诉我怎么做!
  • @bereal: list_ass_slice 在分配给切片的东西上调用PySequence_Fast,这会扼杀使用生成器的任何好处。
  • @thefourtheye 旧列表不会被新列表替换,旧列表会通过切片分配进行修改。您可以在切片分配之前和之后使用id(myl) 进行检查,之后仍然相同。
【解决方案2】:

我们可以用enumerate 遍历列表并用新值替换旧值,像这样

myl = [1, 2, 3, 4, 5, 4, 4, 4, 6]
for idx, item in enumerate(myl):
    if item == 4:
        myl[idx] = 44
print myl
# [1, 2, 3, 44, 5, 44, 44, 44, 6]

【讨论】:

    【解决方案3】:
    while True:
        try:
            myl[myl.index(4)] = 44
        except:
            break
    

    try-except 方法虽然更pythonic,但效率较低。这个timeit program on ideone 至少比较了这里提供的两个答案。

    【讨论】:

    • 这不是更有效。它只是看起来那么好,因为您不小心使用了myl.index[4] 的括号而不是括号。它立即 TypeErrors,但 except 隐藏了错误,因此看起来它立即完成。纠正一下,它看起来不太好。如果您将4s 移到列表的后面,在100 个100s 的大块之后,或者如果您添加更多4s,则这样做的性能劣势变得更加明显。建立一个4s 百分比很高的列表,性能急剧下降。
    • @user2357112 感谢您指出我们的编码错误。
    【解决方案4】:
    for  item in myl:
       if item ==4:
          myl[myl.index(item)]=44
    

    【讨论】:

    • 这实际上对myl没有任何作用。
    • 大声笑,我只是在尝试...对 python 很陌生
    • 这很公平 :) 每个人在某些时候都是新手,但这不是写错误答案可能会误导未来某人的借口。
    • 此外,即使您设法以这种方式分配它,它也会遍历找到的每个 4 的整个列表前缀。使用 O(n^2) 而不是 O(n)
    • @apomene -- 我一天写了很多不好的答案。幸运的是,有一个小“删除”按钮/链接的东西,所以我可以删除它:-)
    猜你喜欢
    • 2018-11-13
    • 2021-06-18
    • 1970-01-01
    • 2020-05-27
    • 2021-01-13
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多