从列表中删除重复的子列表

时间:2015-02-26 23:50:48

标签: python list duplicates duplicate-removal

如果我有这样一个列表:

mylist = [[1,2,3], ['a', 'c'], [3,4,5],[1,2], [3,4,5], ['a', 'c'], [3,4,5], [1,2]]

删除重复子列表的最佳方法是什么?

现在我使用this

y, s = [ ], set( )
for t in mylist:
    w = tuple( sorted( t ) )
    if not w in s:
        y.append( t )
        s.add( w )

它有效,但我想知道是否有更好的方法?更像python的东西?

7 个答案:

答案 0 :(得分:8)

您可以使用OrderedDict.fromkeys过滤列表中的重复项,同时仍保留订单:

>>> from collections import OrderedDict
>>> mylist = [[1,2,3], ['a', 'c'], [3,4,5],[1,2], [3,4,5], ['a', 'c'], [3,4,5], [1,2]]
>>> map(list, OrderedDict.fromkeys(map(tuple, mylist)))
[[1, 2, 3], ['a', 'c'], [3, 4, 5], [1, 2]]
>>>

map(tuple, mylist)是必需的,因为字典键必须是可清除的(列表不是,因为您可以添加/删除项目)。

答案 1 :(得分:6)

将元素转换为元组*,然后将整个事物转换为集合,然后将所有内容转换回列表:

m = [[1,2,3], ['a', 'c'], [3,4,5],[1,2], [3,4,5], ['a', 'c'], [3,4,5], [1,2]]

print [list(i) for i in set(map(tuple, m))]

*我们正在转换为元组,因为列表是不可清除的(因此我们不能在它们上使用set

答案 2 :(得分:5)

好吧,既然set本身就是重复数据删除,那么你的第一直觉可能就是set(mylist)。但是,这并不是很有效:

In [1]: mylist = [[1,2,3], ['a', 'c'], [3,4,5],[1,2], [3,4,5], ['a', 'c'], [3,4,5], [1,2]]

In [2]: set(mylist)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-b352bcae5975> in <module>()
----> 1 set(mylist)

TypeError: unhashable type: 'list'

这是因为set仅适用于iterable个可扩展元素(因为list是可变的,所以它们不可用)。

相反,您只需将子列表转换为子元素的价格即可:

In [3]: set([tuple(x) for x in mylist])
Out[3]: {(1, 2), (1, 2, 3), (3, 4, 5), ('a', 'c')}

或者,如果您确实需要再次列出清单:

In [4]: [list(x) for x in set([tuple(x) for x in mylist])]
Out[4]: [[1, 2], [3, 4, 5], ['a', 'c'], [1, 2, 3]]

答案 3 :(得分:4)

由于您的问题中有sorted(t),我认为您认为[1,2][2,1]

重复

如果这是真的,我会使用frozenset作为内部列表(可以清除)并且不关心子列表的排序。

类似于:

set(frozenset(sublist) for sublist in mylist)

答案 4 :(得分:2)

您不需要排序,您复制的代码中的排序是出于不同的原因进行排序:

seen,out = set(), []

for ele in mylist:
    tp = tuple(ele)
    if tp not in seen:
        out.append(ele)
    seen.add(tp)

答案 5 :(得分:1)

这对你的情况有用:

mylist2 = set(map(tuple, mylist))
print(mylist2) # ('a', 'c'), (3, 4, 5), (1, 2), (1, 2, 3)}

这样可行,因为它会将您的子列表更改为元组,在您的情况下是可以清除的。因此,设置可以采取它们并使其独特。

如果你真的希望输出成为列表列表,你可以这样做:

print(list(map(list,mylist2))) # [['a', 'c'], [3, 4, 5], [1, 2], [1, 2, 3]]

答案 6 :(得分:1)

如果订单和结构(列表清单)不重要,您可以使用

set(map(tuple, my_list))

如果它们很重要,您可以使用列表理解

[e for i,e in enumerate(my_list) if e not in my_list[:i]]

只保留每个元素的第一个副本,因此只保留每个元素中的一个。它稍微慢了

In [16]: timeit.timeit('[e for i,e in enumerate(my_list) if e not in my_list[:i]]', setup="my_list = [[1,2,3], ['a', 'c'], [3,4,5],[1,2], [3,4,5], ['a', 'c'], [3,4,5], [1,2]]")
Out[16]: 1.9146944019994407

In [17]: timeit.timeit('set(map(tuple, my_list))', setup="my_list = [[1,2,3], ['a', 'c'], [3,4,5],[1,2], [3,4,5], ['a', 'c'], [3,4,5], [1,2]]")
Out[17]: 1.3857673469974543

但是如果你关心速度,你应该尝试一种懒散的方法。