繁体   English   中英

Python - 删除列表中前两次出现的元素

[英]Python - Removing first two occurrences of element in list

这个 function 的目标是删除列表中前两次出现的 n。

下面是我写的代码,但几个小时后我仍然弄错了。 一位朋友建议我不要在迭代时编辑列表。 但是,我仍然卡住了。

def remove_first_two(list,n):
    if list == []:
        return []
    else:
        count = 0
        for ele in list:
            if ele == n:
                list.remove(ele)
                count += 1
                if count == 2:
                    break
    return list

list = [1,2,2,3]
print(remove_first_two(list,2)) => [1,2,3] instead of [1,3]

list.remove与 try-except 一起使用两次。 这将删除前两个条目。 复杂度O(n)

list_a = [1,2,3,4]

try:
    list_a.remove(n)
    list_a.remove(n)
    # run a loop too, if it's more than 2
except:
    pass

您可以尝试查找所有索引和删除:

a = [1,2,3,2,3,2,4]
indices = [i for i, x in enumerate(a) if x == 2]
print(indices)

[1, 3, 5]
del a[indices[0]], a[indices[1]]
print(a)

[1, 3, 2, 2, 4]

首先,不要使用“list”作为 Python 中的关键字。使用其他名称,例如“alist”。 下面的代码做你想做的,并保持你已有的基本形式。 您当然也可以使用 built-in.remove() 方法。

def remove_first_two(alist, n):
    if alist == []:
        return []
    else:
        count = 0
        while count < 2:
            for ele in alist:
                if ele == n:
                    alist.remove(ele)
                    count += 1
    return alist

alist = [1,2,2,3]
print(remove_first_two(alist,2)) # Output -> [1,3]

当您的朋友说“不要在迭代时编辑列表”时,他/她是对的,他/她的意思是您应该一起创建另一个列表。 您要执行的操作如下:

def remove_first_two(list, n):
    if list == []:
        return []
    else:
        new_list = []
        count = 0
        for ele in list:
            if ele == n:
                if count >= 2:
                    new_list.append(ele)

                count += 1
            else:
                new_list.append(ele)

    return new_list

但是,请注意,您可以使用一些内置函数来让您的生活更轻松:

list.remove(x)

从列表中删除第一个值等于 x 的项目。 如果没有这样的项目,它会引发 ValueError。

因此,您可以更简单地执行以下操作:

def remove_first_two(list, n):
    if list == []:
        return []

    for _ in range(2):
        if n in list:
            list.remove(n)

    return list

如果您在迭代时更改列表,Python 会更新列表。

在您使用list = [1,2,2,3]时,删除list[1]并且Python 更新list = [1,2,3] 现在 Python 知道您已经迭代到索引 1 并从现在包含3的索引 2 继续。 所以 Python只遇到一次 2

所以听从你朋友的建议,不要在迭代时编辑列表:)

现在您可以使用 Python 的内置list.remove(element)删除元素的第一次出现。 重复 2 次以获得所需的 output。

也 O(n) 与一个单一的解析。

def remove_first_two(mylist,n):
    counter = 0
    def myfilter (i):
        nonlocal counter,n
        if counter > 2:
            return True
        else: 
            counter += 1
            return (i != n)
    return (list(filter(myfilter,mylist)))

这也可以在 python 3.8 中使用列表理解中的赋值表达式来完成:

data = [1,2,3,2,3,2,4]

count = 2
num = 2

[x for x in data if x != num or (count:=count-1) < 0]

结果:

[1, 3, 2, 2, 4]

这是您的程序不起作用的原因:当您删除一个元素时, for循环移动到下一个元素,但通过“继续”它实际上跳过了现在占据已删除元素的 position 的元素。 它会跳过您删除的元素之后的元素。

在删除元素时迭代列表的正确方法是通过使用 while 循环而不是 for 循环来明确索引级数,并且在删除元素时不增加索引:

i = 0 
while i < len(my_list):
    if condition:
        my_list.pop(i)
    else:
        i += 1

但是,在您的情况下,这些都不是必需的! 请注意,当您使用my_list.remove(ele)时,您没有像使用my_list.pop(i)那样提供索引,因此 Python 必须搜索与ele匹配的第一个元素。 虽然单独使用remove会比pop慢,但是这里remove允许你完全不用任何循环,只需要做两次my_list.remove(n)

最后一点:如果您的列表中匹配n的元素少于两个,则两个my_list.remove(n)命令之一将返回ValueError 您可以考虑此异常,知道如果发生这种情况,您的列表已准备就绪,无需采取进一步行动。

所以你需要的代码是:

try:
    my_list.remove(n)
    my_list.remove(n)
except ValueError:
    pass

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM