如何从列表中删除所有子列表的出现

46
我有两个列表:

big_list = [2, 1, 2, 3, 1, 2, 4]
sub_list = [1, 2]

我想从big_list中删除所有sub_list出现的情况。

结果应该是[2, 3, 4]

对于字符串,您可以使用以下内容:

'2123124'.replace('12', '')
据我所知,这种方法无法用于列表。
这不是从列表中删除子列表的重复问题,因为我想从大列表中删除所有子列表。在另一个问题中,结果应该是[5,6,7,1,2,3,4]
更新:为简单起见,在此示例中采用整数。但列表项可以是任意对象。
更新2:
如果big_list = [1, 2, 1, 2, 1]sub_list = [1, 2, 1]
我想要的结果是[2, 1](类似于'12121'.replace('121','')
更新3:
我不喜欢将源代码从StackOverflow粘贴到我的代码中。这就是为什么我在software-recommendations上创建了第二个问题的原因: https://softwarerecs.stackexchange.com/questions/51273/library-to-remove-every-occurrence-of-sub-list-from-list-python 更新4:如果您知道一种可以通过一种方法调用来解决此问题的库,请将其编写为答案,因为这是我首选的解决方案。
测试应通过此测试:
def test_remove_sub_list(self):
    self.assertEqual([1, 2, 3], remove_sub_list([1, 2, 3], []))
    self.assertEqual([1, 2, 3], remove_sub_list([1, 2, 3], [4]))
    self.assertEqual([1, 3], remove_sub_list([1, 2, 3], [2]))
    self.assertEqual([1, 2], remove_sub_list([1, 1, 2, 2], [1, 2]))
    self.assertEquals([2, 1], remove_sub_list([1, 2, 1, 2, 1], [1, 2, 1]))
    self.assertEqual([], remove_sub_list([1, 2, 1, 2, 1, 2], [1, 2]))

2
可能是从列表中删除子列表的重复问题。 - glibdud
2
@Marcus.Aurelianus 可能是因为那个答案上的大多数赞发生在几天内:Stack Overflow 每天的声望上限为200。因此,如果超过20人在24小时内给您的答案点赞,则只计算前20个点赞(×10 = 200分)。 - Konrad Rudolph
2
@guettli. 为什么不将函数放到你的库中,然后将其用作一行代码呢? - Mad Physicist
4
考虑到你之前说过的话,最后那句话“我喜欢重复使用软件”的说法充其量是虚伪的。除了你所加的完全人为的限制以外,没有任何阻止你重新使用软件的因素。 - Mad Physicist
2
如果有一个外部库可以解决这个问题,你是需要一个用C语言编写的优化解决方案,还是接受用Python实现的东西?在后一种情况下,我可以将我的解决方案上传到GitHub,并附带一个setup.py文件来调用它。 - Mad Physicist
显示剩余14条评论
13个回答

0

你可以在生成器中使用递归:

def remove(d, sub_list):
   if d[:len(sub_list)] == sub_list and len(sub_list) <= len(d[:len(sub_list)]):
      yield from [[], remove(d[len(sub_list):], sub_list)][bool(d[len(sub_list):])]
   else:
      yield d[0]
      yield from [[], remove(d[1:], sub_list)][bool(d[1:])]

tests = [[[2, 1, 2, 3, 1, 2, 4], [1, 2]], [[1, 2, 1, 2], [1, 2]], [[1, 'a', int, 3, float, 'a', int, 5], ['a', int]], [[1, 1, 1, 1, 1], [1,1,1]]]
for a, b in tests:
  print(list(remove(a, b)))

输出:

[2, 3, 4]
[]
[1, 3, <class 'float'>, 5]
[1, 1]

0

只是为了好玩,这里是最接近一行代码的近似:

from functools import reduce

big_list = [2, 1, 2, 3, 1, 2, 4]
sub_list = [1, 2]
result = reduce(lambda r, x: r[:1]+([1]+r[2:-r[1]],[min(len(r[0]),r[1]+1)]+r[2:])[r[-r[1]:]!=r[0]]+[x], big_list+[0], [sub_list, 1])[2:-1]

不相信它能工作吗?请查看on IDEone

当然,它远非高效且难以理解,但它应该有助于说服 OP 接受@Mad Physicist's answer


当然,这远非高效且难以理解,但它应该有助于说服 OP 接受 @Mad Physicist 的答案。加一分给他。 - Chris_Rands

0

您想要实现的目标可以通过将其转换为字符串列表并在替换后再将其转换为整数类型来完成。

在一行代码中,您可以这样做

map(int,list(("".join(map(str, big_list))).replace("".join(map(str, sub_list)),'').replace(''.join((map(str, sub_list))[::-1]),'')))

输入

big_list = [1, 2, 1, 2, 1]
sub_list = [1, 2, 1]

输出

[2, 1]

输入

big_list = [2, 1, 2, 3, 1, 2, 4]
sub_list = [1, 2]

输出

[2, 3, 4]


1
根据问题描述,这个方法适用于任何类型:对象、类等。据我所知,你无法将每个对象转换为字符串。你可以将它们序列化成字符串……但这听起来很奇怪。 - guettli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接