[英]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.