繁体   English   中英

如果元组在 Python 中包含两个相邻的“1”,如何从列表中删除元组?

[英]How can I remove a tuple from a list if the tuple contains two "1" next to each other in Python?

我有一个元组列表:

from itertools import product
l1 = list((product((0,1), repeat = n))) 

对于 n=4,输出如下:

 [(0, 0, 0, 0),
 (0, 0, 0, 1),
 (0, 0, 1, 0),
 (0, 0, 1, 1),
 (0, 1, 0, 0),
 (0, 1, 0, 1),
 (0, 1, 1, 0),
 (0, 1, 1, 1),
 (1, 0, 0, 0),
 (1, 0, 0, 1),
 (1, 0, 1, 0),
 (1, 0, 1, 1),
 (1, 1, 0, 0),
 (1, 1, 0, 1),
 (1, 1, 1, 0),
 (1, 1, 1, 1)]

我想删除至少有两个“1”彼此相邻的元组,例如(0,1,1,0)

我试过这个:

for i in l1:
    for j in i:
         if j==1 and j+1 == 1:
                l1.remove(i)

我想这是行不通的,因为它需要 j+1 作为实际数字 + 1,就像如果 j=1 它需要 2 等等。

我应该怎么做?

您可以使用zip(i, i[1:])构建邻居对并检查它们是否包含(1, 1)

>>> [i for i in l1 if (1, 1) not in zip(i, i[1:])]
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0),
 (0, 1, 0, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0)]

您的方法合乎逻辑,但不幸的是在 Python(或大多数其他语言)中不起作用,并且实现不正确,因为j==1 and j+1 == 1永远不会正确; 如果j等于 1,则j+1等于 2,周期。 但更大的问题是您试图在迭代列表时从列表中删除内容,这是一个禁忌。

首先让我们解决如何检查两个1是否彼此相邻的问题。 不是查看jj+1 ,我们需要查看t[j]t[j+1] ,其中t是元组之一。 此外, j需要迭代到长度减 1,否则t[j+1]将在元组的末尾给出一个IndexError any函数是一种方便的方法:

any(t[j] == t[j+1] == 1 for j in range(n - 1))

请注意,由于链式比较t[j] == t[j+1] == 1在 Python 中有效。

现在让我们解决如何从列表中删除这些元素的问题。 简单地用您想要的元素构建一个新列表要方便得多,而不是删除您不想要的元素。 列表推导式是一种方便的方法:

result = [
    t for t in product((0, 1), repeat=n)
    if not any(t[j] == t[j+1] == 1 for j in range(n - 1))
]

结果:

[(0, 0, 0, 0),
 (0, 0, 0, 1),
 (0, 0, 1, 0),
 (0, 1, 0, 0),
 (0, 1, 0, 1),
 (1, 0, 0, 0),
 (1, 0, 0, 1),
 (1, 0, 1, 0)]

综上所述,对于较大的 n,使用仅生成您想要的元素的算法会更有效,而不是遍历整个笛卡尔积(大小为 2 n )并拒绝您不想要的元素。

这应该可以解决问题:

>>> n = 4
>>> from itertools import product
>>> l1 = list((product((0,1), repeat = n))) 
>>> l1
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]
>>> [t for t in l1 if not any(t[i] == 1 and t[i+1] == 1 for i in range(n-1))]
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0), (0, 1, 0, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0)]

not any(t[i] == 1 and t[i+1] == 1 for i in range(n-1))条件基本上检查连续元素是否等于 1。 请注意range(n-1)索引迭代器 - 我们不想根据第n +1 个元素检查第n个元素,因为上面的任何元组中都没有第五个元素。

定时

请注意,我的函数大约是 Heap Overflow 的两倍。

>>> from time import time as t
>>> def f1():
...     t0 = t()
...     result = [i for i in l1 if (1, 1) not in zip(i, i[1:])]
...     t1 = t()
...     print(t1-t0)
... 
>>> def f2():
...     t0 = t()
...     result = [t for t in l1 if not any(t[i] == 1 and t[i+1] == 1 for i in range(n-1))]
...     t1 = t()
...     print(t1-t0)
... 
>>> l1 = list((product((0,1), repeat = n))) * 1000000
>>> len(l1)
16000000
>>> f1()
8.146391868591309
>>> f2()
18.645386934280396

添加一个不那么“pythonic”但更具可读性的示例以供考虑:

def filter_helper(t):
  for i, val in enumerate(t):
    if i != 0 and (t[i-1]) == val and val == 1:
      return False  
  return True

print(list(filter(filter_helper, a)))

其中a是元组的原始列表。

也可以使用 forloop 和 python 的 any() 方法来完成

for x in l1:
    if any([(x[i]==x[i+1]==1) for i in x]) == True:
        l1.remove(x)

暂无
暂无

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

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