如何仅用一个语句从列表中删除多个项目?

问题描述 投票:0回答:10

在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
只接受一个参数。

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

附注我用过

del
remove
。谁能解释一下这两者之间的区别,或者它们是相同的吗?

python list list-comprehension
10个回答
266
投票

在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)
是一小组元素),使用
set
会更快,因为
in
操作平均时间复杂度为O(1) 。首先构建您要删除的可迭代也是一个好主意,这样您就不会在列表理解的每次迭代中都创建它:

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]
如果内存不便宜,

bloom 过滤器也是一个很好的解决方案。


50
投票

您可以通过将列表转换为

set
并使用
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))

会给你以下输出:

final_list = [3.14, True]

注意:这将删除输入列表中的重复项,并且输出中的元素可以按任何顺序排列(因为

set
不保留顺序)。它还要求两个列表中的所有元素都是可哈希


2
投票

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


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

文档字符串扩展:

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

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


2
投票

您可以使用 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]

1
投票

你可以使用这个 -

假设我们有一个列表,

l = [1,2,3,4,5]

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

del l[3:]

我们有输出:

l = [1,2,3]

保持简单


0
投票

我不知道为什么大家都忘记提及Python中

set
的惊人能力。您可以简单地将列表转换为一个集合,然后用一个简单的表达式删除您想要删除的任何内容,如下所示:

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

0
投票

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

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

ind=item_list.index('item')

然后删除对应的值:

del item_list[ind]

.index(value) 获取第一个出现的值,而 .remove(value) 删除第一个出现的值。不客气。


0
投票

假设我们有如下的my_list。我们想从列表中删除重复的 0。通过使用remove(),只能删除一个0,而下一个代码可以一次删除所有重复的0:

my_list = [1, 2, 3, 0, 0, 0, 3, 4]
list(filter(lambda a: a != 0, my_list))

output:

[1, 3, 3, 4]

0
投票

我们可以删除多个元素

列表1=[1,2,3,4,5,200,30]

删除列表1[1:3]

打印(列表1)

[1,4,5,200,30]


0
投票

您可以将 numpy 数组和 set 函数结合起来,得到一个仅显示您想要保留的元素的新数组。

import numpy as np
# given an array A:
A = [5,78,423,87,45,78,4]
# first convert your array to a numpy array
A_np = np.array(A)
# specify the indices you want to remove
inds_to_be_deleted = [3,5]
# find the remaining indices using set function
remaining_inds = list(set(range(len(A)))-set(inds_to_be_deleted))
# the new array will only contain the elements at the remaining indices
A_new = A_np[remaining_inds]

这会给你这个输出: 数组([ 5, 78, 423, 45, 4])

© www.soinside.com 2019 - 2024. All rights reserved.