[英]Remove sublist duplicates including reversed
例如我有以下
list = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
如果子列表在同一列表中具有反向子列表(即 ['1', '2'] = ['2', '1']),我想匹配,並且如果為 True,則從列表中刪除鏡像一。
最終列表應如下所示:
list = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5']['2', '6']]
這是我嘗試過的:
for i in range(len(list)):
if list[i] == list[i][::-1]:
print("Match found")
del list[i][::-1]
print(list)
但最后我得到了與原始列表相同的列表。 我不確定我的匹配條件是否正確。
您可以遍歷列表的元素,並使用一個set
來跟蹤到目前為止已經看到的那些。 使用集合是檢查成員資格的一種更方便的方法,因為該操作的復雜性較低,在這種情況下,您需要使用元組,因為列表不是可散列的。 如果沒有看到實際的元組或reversed
的,則只需保留這些項目(如果你只想忽略那些有反轉的項目,你只需要if tuple(reversed(t)) in s
):
s = set()
out = []
for i in l:
t = tuple(i)
if t in s or tuple(reversed(t)) in s:
continue
s.add(t)
out.append(i)
print(out)
# [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '6']]
lists = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
for x in lists:
z=x[::-1]
if z in lists:
lists.remove(z)
解釋:在遍歷列表時,反轉每個元素並存儲在“z”中。 現在,如果列表中存在“z”,請使用 remove() 將其刪除
您的解決方案的問題是您在使用索引“i”時進行檢查,這意味着“i”處的元素是否等於它的反向元素,這永遠不會發生! 因此得到相同的結果
方法1:
new_list = []
for l in List:
if l not in new_list and sorted(l) not in new_list:
new_list.append(l)
print(new_list)
方法2:
你也可以這樣嘗試:
seen = set()
print([x for x in List if frozenset(x) not in seen and not seen.add(frozenset(x))])
[['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '6']]
my_list = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
my_list = list(set([sorted(l) for l in my_list]))
這類似於@Mehul Gupta 的解決方案,但我認為他們的解決方案是在匹配時遍歷列表兩次:一次用於檢查,一次用於刪除。 相反,我們可以
the_list = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
for sub_list in the_list:
try:
idx = the_list.index(sub_list[::-1])
except ValueError:
continue
else:
the_list.pop(idx)
print(the_list)
# [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '6']]
因為請求寬恕比請求許可更容易。
注意:在循環時刪除元素不是一件好事,但對於這個特定問題,它沒有害處。 事實上,這更好,因為我們不再檢查鏡像; 我們已經刪除了它。
正如我在評論中所寫,切勿使用list
(或任何內置)作為變量名:
L = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
看看你的代碼:
for i in range(len(L)):
if L[i] == L[i][::-1]:
print("Match found")
del L[i][::-1]
有兩個問題。 首先,您將L[i]
與L[i][::-1]
進行比較,但您想將L[i]
與L[j][::-1]
進行比較,以獲得任何j != i
。 其次,您嘗試在迭代期間刪除列表的元素。 如果刪除一個元素,則列表長度會減少,並且循環的索引將超出列表的范圍:
>>> L = [1,2,3]
>>> for i in range(len(L)):
... del L[i]
...
Traceback (most recent call last):
...
IndexError: list assignment index out of range
要解決第一個問題,您可以對元素進行兩次迭代:對於每個元素,是否還有另一個元素與第一個元素相反? 要解決第二個問題,您有兩個選擇: 1. 建立一個新列表; 2. 以相反的順序進行,首先刪除最后一個索引。
第一個版本:
new_L = []
for i in range(len(L)):
for j in range(i+1, len(L)):
if L[i] == L[j][::-1]:
print("Match found")
break
else: # no break
new_L.append(L[i])
print(new_L)
第二個版本:
for i in range(len(L)-1, -1, -1):
for j in range(0, i):
if L[i] == L[j][::-1]:
print("Match found")
del L[i]
print(L)
(要獲得更好的時間復雜度,請參閱@yatu 的回答。)
對於單線,您可以使用functools
模塊:
>>> L = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
>>> import functools
>>> functools.reduce(lambda acc, x: acc if x[::-1] in acc else acc + [x], L, [])
[['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '6']]
邏輯與第一版的邏輯相同。
你也可以試試這個:-
l = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]
res = []
for sub_list in l:
if sub_list[::-1] not in res:
res.append(sub_list)
print(res)
Output:-
[['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '6']]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.