简体   繁体   English

删除子列表重复项,包括反转

[英]Remove sublist duplicates including reversed

For example i have following例如我有以下

list = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]

I want to match if a sub list has a reversed sub list within same list (ie ['1', '2'] = ['2', '1']), and if True than to remove from the list the mirrored one.如果子列表在同一列表中具有反向子列表(即 ['1', '2'] = ['2', '1']),我想匹配,并且如果为 True,则从列表中删除镜像一。

The final list should look like:最终列表应如下所示:

list = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5']['2', '6']]

This is what i tried:这是我尝试过的:

for i in range(len(list)):
    if list[i] == list[i][::-1]:
            print("Match found")
            del list[i][::-1]

print(list)

But finally I get the same list as original.但最后我得到了与原始列表相同的列表。 I am not sure if my matching condition is correct.我不确定我的匹配条件是否正确。

You could iterate over the elements of the list, and use a set to keep track of those that have been seen so far.您可以遍历列表的元素,并使用一个set来跟踪到目前为止已经看到的那些。 Using a set is a more convenient way to check for membership, since the operation has a lower complexity , and in that case you'll need to work with tuples, since lists aren't hashable.使用集合是检查成员资格的一种更方便的方法,因为该操作的复杂性较低,在这种情况下,您需要使用元组,因为列表不是可散列的。 Then just keep those items if neither the actual tuple or the reversed have been seen (if you just want to ignore those which have a reversed you just need if tuple(reversed(t)) in s ):如果没有看到实际的元组或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)

Explanation: While looping over lists, reverse each element and store in 'z'.解释:在遍历列表时,反转每个元素并存储在“z”中。 Now, if 'z' exists in lists, remove it using remove()现在,如果列表中存在“z”,请使用 remove() 将其删除

The problem with your solution is you are checking while using index 'i' which means if an element at 'i' is equal to its reverse which can never happen!!您的解决方案的问题是您在使用索引“i”时进行检查,这意味着“i”处的元素是否等于它的反向元素,这永远不会发生! hence getting the same results因此得到相同的结果

Approach1:方法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)

Approach2:方法2:

You can try like this also:你也可以这样尝试:

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]))

This is similar to solution by @Mehul Gupta, but I think their solution is traversing the list twice if matched: one for checking and one for removing.这类似于@Mehul Gupta 的解决方案,但我认为他们的解决方案是在匹配时遍历列表两次:一次用于检查,一次用于删除。 Instead, we could相反,我们可以

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']]

because it is easier to ask for forgiveness than permission .因为请求宽恕比请求许可更容易

Note: Removing elements whilst looping is not a good thing but for this specific problem, it does no harm.注意:在循环时删除元素不是一件好事,但对于这个特定问题,它没有害处。 In fact, it is better because we do not check the mirrored again;事实上,这更好,因为我们不再检查镜像; we already removed it.我们已经删除了它。

As I have written in a comment, do never use list (or any built-in) as a variable name:正如我在评论中所写,切勿使用list (或任何内置)作为变量名:

L = [['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '1'], ['4', '1'], ['2', '6']]

Have a look at your code:看看你的代码:

for i in range(len(L)):
    if L[i] == L[i][::-1]:
        print("Match found")
        del L[i][::-1]

There are two issues.有两个问题。 First, you compare L[i] with L[i][::-1] , but you want to compare L[i] with L[j][::-1] for any j != i .首先,您将L[i]L[i][::-1]进行比较,但您想将L[i]L[j][::-1]进行比较,以获得任何j != i Second, you try to delete elements of a list during an iteration.其次,您尝试在迭代期间删除列表的元素。 If you delete an element, then the list length is decreased and the index of the loop will be out of the bounds of list:如果删除一个元素,则列表长度会减少,并且循环的索引将超出列表的范围:

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

To fix the first issue, you can iterate twice over the elements: for each element, is there another element that is the reverse of the first?要解决第一个问题,您可以对元素进行两次迭代:对于每个元素,是否还有另一个元素与第一个元素相反? To fix the second issue, you have two options: 1. build a new list;要解决第二个问题,您有两个选择: 1. 建立一个新列表; 2. proceed in reverse order, to delete first the last indices. 2. 以相反的顺序进行,首先删除最后一个索引。

First version:第一个版本:

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)    

Second version:第二个版本:

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)    

(For a better time complexity, see @yatu's answer.) (要获得更好的时间复杂度,请参阅@yatu 的回答。)


For a one-liner, you can use the functools module :对于单线,您可以使用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']]

The logic is the same as the logic of the first version.逻辑与第一版的逻辑相同。

You can try this also:-你也可以试试这个:-

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:- Output:-

[['1', '2'], ['1', '3'], ['1', '4'], ['1', '5'], ['2', '6']]

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

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