只需一条语句即可从 Python 列表中删除多项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36268749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 17:40:00  来源:igfitidea点击:

Remove multiple items from a Python list in just one statement

python

提问by RandomCoder

In python, I know how to remove items from a list.

在 python 中,我知道如何从列表中删除项目。

item_list = ['item', 5, 'foo', 3.14, True]
item_list.remove('item')
item_list.remove(5)

This above code removes the values 5 and 'item' from item_list. But when there is a lot of stuff to remove, I have to write many lines of

上面的代码从 item_list 中删除了值 5 和 'item'。但是当有很多东西要删除时,我必须写很多行

item_list.remove("something_to_remove")

If I know the index of what I am removing, I use:

如果我知道要删除的内容的索引,我会使用:

del item_list[x]

where x is the index of the item I want to remove.

其中 x 是我要删除的项目的索引。

If I know the index of all of the numbers that I want to remove, I'll use some sort of loop to delthe items at the indices.

如果我知道要删除的所有数字的索引,我将对del索引处的项目使用某种循环。

But what if I don't know the indices of the items I want to remove?

但是,如果我不知道要删除的项目的索引怎么办?

I tried item_list.remove('item', 'foo'), but I got an error saying that removeonly takes one argument.

我试过了item_list.remove('item', 'foo'),但我收到一个错误,说remove只需要一个参数。

Is there a way to remove multiple items from a list in a single statement?

有没有办法在单个语句中从列表中删除多个项目?

P.S. I've used deland remove. Can someone explain the difference between these two, or are they the same?

PS我用过delremove。有人可以解释这两者之间的区别,还是它们相同?

Thanks

谢谢

回答by aluriak

In Python, create a new object is often better than modify an existing one:

在 Python 中,创建新对象通常比修改现有对象更好:

item_list = ['item', 5, 'foo', 3.14, True]
item_list = [e for e in item_list if e not in ('item', 5)]

Which is equivalent to:

这相当于:

item_list = ['item', 5, 'foo', 3.14, True]
new_list = []
for e in item_list:
    if e not in ('item', 5):
        new_list.append(e)
item_list = new_list


In case of a big list of filtered out values (here, ('item', 5)is a small set of element), use a setcan lead to performance improvement, as the inoperation is in O(1) :

如果过滤掉的值列表很大(这里('item', 5)是一小组元素),使用 aset可以提高性能,因为in操作在 O(1) 中:

item_list = [e for e in item_list if e not in {'item', 5}]

Note that, as explained in comments and suggested here, the following could save even more time, avoiding the set to be built at each loop:

请注意,正如评论中所解释和建议的here,以下可以节省更多时间,避免在每个循环中构建集合:

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]

A bloom filteris also a good solution if memory is not cheap.

一个布隆过滤器也是一个不错的解决方案,如果内存是不便宜。

回答by Aakash Goel

item_list = ['item', 5, 'foo', 3.14, True]
list_to_remove=['item', 5, 'foo']

final list after removing should be as follow

删除后的最终列表应如下

final_list=[3.14, True]

Single Line Code

单行代码

final_list= list(set(item_list).difference(set(list_to_remove)))

output would be as follow

输出如下

final_list=[3.14, True]

回答by Anwarvic

I don't know why everyone forgot to mention the amazing capability of sets in python. You can simply cast your list into a set and then remove whatever you want to remove in a simple expression like so:

不知道为什么大家忘了提setpython中s的惊人能力。您可以简单地将您的列表转换为一个集合,然后在一个简单的表达式中删除您想要删除的任何内容,如下所示:

>>> item_list = ['item', 5, 'foo', 3.14, True]
>>> item_list = set(item_list) - {'item', 5}
>>> item_list
{True, 3.14, 'foo'}
>>> # you can cast it again in a list-from like so
>>> item_list = list(item_list)
>>> item_list
[True, 3.14, 'foo']

回答by Darkonaut

I'm reposting my answer from herebecause I saw it also fits in here. It allows removing multiple values or removing only duplicates of these values and returns either a new list or modifies the given list in place.

我从这里重新发布我的答案,因为我看到它也适合这里。它允许删除多个值或仅删除这些值的重复项,并返回一个新列表或就地修改给定列表。



def removed(items, original_list, only_duplicates=False, inplace=False):
    """By default removes given items from original_list and returns
    a new list. Optionally only removes duplicates of `items` or modifies
    given list in place.
    """
    if not hasattr(items, '__iter__') or isinstance(items, str):
        items = [items]

    if only_duplicates:
        result = []
        for item in original_list:
            if item not in items or item not in result:
                result.append(item)
    else:
        result = [item for item in original_list if item not in items]

    if inplace:
        original_list[:] = result
    else:
        return result

Docstring extension:

文档字符串扩展:

"""
Examples:
---------

    >>>li1 = [1, 2, 3, 4, 4, 5, 5]
    >>>removed(4, li1)
       [1, 2, 3, 5, 5]
    >>>removed((4,5), li1)
       [1, 2, 3]
    >>>removed((4,5), li1, only_duplicates=True)
       [1, 2, 3, 4, 5]

    # remove all duplicates by passing original_list also to `items`.:
    >>>removed(li1, li1, only_duplicates=True)
      [1, 2, 3, 4, 5]

    # inplace:
    >>>removed((4,5), li1, only_duplicates=True, inplace=True)
    >>>li1
        [1, 2, 3, 4, 5]

    >>>li2 =['abc', 'def', 'def', 'ghi', 'ghi']
    >>>removed(('def', 'ghi'), li2, only_duplicates=True, inplace=True)
    >>>li2
        ['abc', 'def', 'ghi']
"""


You should be clear about what you really want to do, modify an existing list, or make a new list with the specific items missing. It's important to make that distinction in case you have a second reference pointing to the existing list. If you have, for example...

您应该清楚自己真正想要做什么,修改现有列表,或者创建一个缺少特定项目的新列表。如果您有指向现有列表的第二个引用,则进行区分很重要。例如,如果您有...

li1 = [1, 2, 3, 4, 4, 5, 5]
li2 = li1
# then rebind li1 to the new list without the value 4
li1 = removed(4, li1)
# you end up with two separate lists where li2 is still pointing to the 
# original
li2
# [1, 2, 3, 4, 4, 5, 5]
li1
# [1, 2, 3, 5, 5]

This may or may not be the behaviour you want.

这可能是也可能不是您想要的行为。

回答by aless80

But what if I don't know the indices of the items I want to remove?

但是,如果我不知道要删除的项目的索引怎么办?

I do not exactly understand why you do not like .remove but to get the first index corresponding to a value use .index(value):

我不完全明白为什么你不喜欢 .remove 而是获取与值对应的第一个索引使用 .index(value):

ind=item_list.index('item')

then remove the corresponding value:

然后删除相应的值:

del item_list.pop[ind]

.index(value) gets the first occurrence of value, and .remove(value) removes the first occurrence of value

.index(value) 获取第一次出现的 value, .remove(value) 移除第一次出现的 value

回答by Vlad Bezden

You can use filterfalsefunction from itertoolsmodule

您可以使用itertools模块中的filterfalse函数

Example

例子

import random
from itertools import filterfalse

random.seed(42)

data = [random.randrange(5) for _ in range(10)]
clean = [*filterfalse(lambda i: i == 0, data)]
print(f"Remove 0s\n{data=}\n{clean=}\n")


clean = [*filterfalse(lambda i: i in (0, 1), data)]
print(f"Remove 0s and 1s\n{data=}\n{clean=}")

Output:

输出:

Remove 0s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 1, 1, 1, 4, 4]

Remove 0s and 1s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 4, 4]

回答by Krishna Singhal

You Can use this -

你可以用这个 -

Suppose we have a list, l = [1,2,3,4,5]

假设我们有一个列表, l = [1,2,3,4,5]

We want to delete last two items in a single statement

我们想删除单个语句中的最后两项

del l[3:]

We have output:

我们有输出:

l = [1,2,3]

l = [1,2,3]

Keep it Simple

把事情简单化