在Python中移除列表中的重复子列表

4 投票
4 回答
3847 浏览
提问于 2025-04-18 07:30

我在这里看到了一些相关的问题,但它们的回答对我没有帮助。我有一个包含多个子列表的列表,其中一些子列表是重复的,但它们的元素可能是乱序的。比如说:

g = [[1, 2, 3], [3, 2, 1], [1, 3, 2], [9, 0, 1], [4, 3, 2]]

根据我的问题,输出应该是这样的:

g = [[1,2,3],[9,0,1],[4,3,2]]

我尝试过用 set 来处理,但它只会去掉那些完全相同的列表(我以为这样可以,因为集合本身是无序的)。我看到的其他问题只有一些完全重复的列表的例子,比如这个链接:Python : 如何在列表中去除重复的列表?。目前输出的顺序(对于列表和子列表)不是问题。

4 个回答

1

那我们来看看roippi提到的使用frozenset的方式:

>>> g = [list(x) for x in set(frozenset(i) for i in [set(i) for i in g])]

[[0, 9, 1], [1, 2, 3], [2, 3, 4]]
1

我会把列表中的每个元素都转换成一个不可变集合(也就是可以被哈希的),然后再用这些不可变集合创建一个集合,这样就能去掉重复的元素:

>>> g = [[1, 2, 3], [3, 2, 1], [1, 3, 2], [9, 0, 1], [4, 3, 2]]
>>> set(map(frozenset, g))
set([frozenset([0, 9, 1]), frozenset([1, 2, 3]), frozenset([2, 3, 4])])

如果你需要把这些元素再转换回列表的话:

>>> map(list, set(map(frozenset, g)))
[[0, 9, 1], [1, 2, 3], [2, 3, 4]]
3

如果你不在乎列表和子列表的顺序(而且子列表里的所有项目都是独一无二的):

result = set(map(frozenset, g))

如果子列表可能有重复的项目,比如说 [1, 2, 1, 3],那么你可以用 tuple(sorted(sublist)) 来代替 frozenset(sublist),这样可以去掉子列表中的重复项。

如果你想保持子列表的顺序:

def del_dups(seq, key=frozenset):
    seen = {}
    pos = 0
    for item in seq:
        if key(item) not in seen:
            seen[key(item)] = True
            seq[pos] = item
            pos += 1
    del seq[pos:]

举个例子:

del_dups(g, key=lambda x: tuple(sorted(x)))

可以查看这个链接:在Python中,去掉列表中的重复项,确保所有元素都是独一无二的同时,保持顺序的最快算法是什么?

7

这是在讲一个关于列表推导式的技巧,可能有点复杂:

seen = set()

[x for x in g if frozenset(x) not in seen and not seen.add(frozenset(x))]
Out[4]: [[1, 2, 3], [9, 0, 1], [4, 3, 2]]

对于那些(不像我)不喜欢这样使用副作用的人来说:

res = []
seen = set()

for x in g:
    x_set = frozenset(x)
    if x_set not in seen:
        res.append(x)
        seen.add(x_set)

你把 frozenset 加入集合的原因是,因为你只能把可哈希的对象放进 set 里,而普通的 set 是不可哈希的。

撰写回答