簡體   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