删除列表中的元素或重新创建新列表 (Python)

huangapple go评论74阅读模式
英文:

Deleting elements from list or recreating new list (python)

问题

删除列表中的对象的最佳/最快方式是什么?删除一些对象:

[objects.remove(o) for o in objects if o.x <= 0]

或者重新创建新的对象:

new_objects = [o for o in objects if o.x > 0]
英文:

What it the best/fastest way to delete objects from list?
Deleting some objects:

[objects.remove(o) for o in objects if o.x &lt;= 0]

or recreating new object:

new_objects = [o for o in objects if o.x &gt; 0]

答案1

得分: 3

首先,不要在列表理解中用于副作用。这会不必要地创建一个None列表,然后被忽略并垃圾回收,这样的写法是不好的。列表理解适用于函数式映射/过滤操作,用于创建新列表。

然而,即使将其转换为等效的循环,仍然存在一个经典错误:

>>> objects = [1,1,2,2,1,1]
>>> for obj in objects:
...     if obj == 2:
...         objects.remove(obj)
...
>>> objects
[1, 1, 2, 1, 1]

这是因为内部迭代器本质上保持索引,然后简单地递增。由于通过移除一个项目改变了列表的大小,每个索引都会向下移动,一个项目会被跳过。因此,当有两个连续匹配的项目需要被移除时,一个会被跳过。

但更重要的是,在循环中从列表中移除项目即使正确执行也是低效的。

这是二次时间复杂度,而创建新列表是线性的。所以实际上,我认为创建新列表的明显优势是这样的。

正如@Selcuk在评论中指出的,修改列表的优势在于不使用辅助空间。

英文:

For starters, don't use list comprehensions for side effects. It needlessly creates a list of None's here, which is simply ignored and garbage collected, and is just bad style. List comprehensions are for functional mapping/filtering operations to create new lists.

However, even converted to an equivalent loop there is a classic bug:

&gt;&gt;&gt; objects = [1,1,2,2,1,1]
&gt;&gt;&gt; for obj in objects:
...     if obj == 2:
...         objects.remove(obj)
...
&gt;&gt;&gt; objects
[1, 1, 2, 1, 1]

This is because the internal iterator essentially keeps and index which it simply increments. Since the list changes size by removing an item, every index is shifted down, and an item is skipped. So when there are two matching items to be removed in a row, one is skipped.

But more to the point, removing from a list in a loop is inefficient even if you do it correctly.

It is quadratic time, whereas creating the new list is linear. So really, I think those are the clear advantages of creating a new list.

As pointed out by @Selcuk in the comments, the advantage of modifying the list is that you don't use auxiliary space.

答案2

得分: 2

在迭代时以这种方式修改列表可能会存在潜在问题。当你从列表中移除一个项目时,剩余项目的索引会减一,如果你试图通过索引访问它可能会出现问题。

最好的方法是使用 del 语句,因为它比 remove() 方法更快,它避免了在列表中搜索要移除的项目的需要。

i = 0
while i < len(objects):
    if objects[i].x <= 0:
        del objects[i]
    else:
        i += 1

只是代码的可读性现在降低了。

关于重新创建与更新的问题,毫无疑问,重新创建更快,因为在更新时索引会一再改变,创建一个新列表可以避免在列表中剩余项目的索引移动。但是,如果列表很大,这可能会显著增加空间复杂性。

对于解决问题的更快方法,你可以考虑使用生成器表达式而不是列表推导式。生成器表达式类似于列表推导式,但它产生一个可以惰性迭代的生成器对象,而不是在内存中创建一个新列表。

new_objects = (o for o in objects if o.x > 0)

有关生成器表达式的更多信息,请参考:https://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehensions

英文:

There is a potential issue with modifying a list this way while iterating over it. When you remove an item from the list, the indices of the remaining items shift down by one, which might be an issue if you are trying to access it by index.

The best method is using a del statement as it is faster than remove() method, because it avoids the need to search the list for the item to remove.

    i = 0
while i &lt; len(objects):
    if objects[i].x &lt;= 0:
        del objects[i]
    else:
        i += 1

Just the the readability of code has decreased now .

For question of recreating vs updating , no doubt recreating is faster as while updating the index gets changed again and again , creating a new list avoids the need to shift the indices of the remaining items in the list.
But it can increase the space complexity by huge amount if the list is large.

For a faster way of your problem you can consider a generator expression instead of a list comprehension. A generator expression is similar to a list comprehension, but it produces a generator object that can be iterated over lazily, rather than creating a new list in memory.

new_objects = (o for o in objects if o.x &gt; 0)

For more information about generator expression , you can check this out : https://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehensions

huangapple
  • 本文由 发表于 2023年2月16日 13:39:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468249.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定