问题:仅需一条语句即可从Python列表中删除多个项目

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

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

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

item_list.remove("something_to_remove")

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

del item_list[x]

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

如果我知道要删除的所有数字del的索引,则将对索引项进行某种循环。

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

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

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

PS我已经使用delremove。有人可以解释这两者之间的区别还是相同?

谢谢

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

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.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.

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

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 remove only takes one argument.

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

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

Thanks


回答 0

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

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

等效于:

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

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

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

请注意,正如注释中所建议和此处建议的那样,以下内容可以节省更多时间,避免在每个循环中构建该集合:

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

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

In Python, creating a new object is often better than modifying an existing one:

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 elements), using a set is faster as the in operation is O(1) time complexity on average. It’s also a good idea to build the iterable you’re removing first, so that you’re not creating it on every iteration of the list comprehension:

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

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


回答 1

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

删除后的最终清单应如下

final_list=[3.14, True]

单行代码

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

输出如下

final_list=[3.14, True]

You can do it in one line by converting your lists to sets and using set.difference:

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

final_list = list(set(item_list) - set(list_to_remove))

Would give you the following output:

final_list = [3.14, True]

Note: this will remove duplicates in your input list and the elements in the output can be in any order (because sets don’t preserve order). It also requires all elements in both of your lists to be hashable.


回答 2

我不知道为什么每个人都忘记提及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']

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:

>>> 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']

回答 3

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


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扩展名:

"""
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']
"""

您应该清楚自己真正想要做的事情,修改现有列表或创建缺少特定项目的新列表。如果您还有第二个引用指向现有列表,则必须进行区分。例如,如果您有…

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]

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

I’m reposting my answer from here because 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.


回答 4

您可以从itertools模块使用filterfalse函数

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=}")

输出:

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]

You can use filterfalse function from itertools module

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]

回答 5

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

我不完全理解为什么您不喜欢.remove而是使用.index(value)获得与值相对应的第一个索引:

ind=item_list.index('item')

然后删除相应的值:

del item_list.pop[ind]

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

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):

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


回答 6

您可以使用此-

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

我们要在单个语句中删除最后两个项目

del l[3:]

我们输出:

l = [1,2,3]

把事情简单化

You Can use this –

Suppose we have a list, 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]

Keep it Simple


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。