Python:删除列表列表中的重复项

时间:2014-06-20 15:31:57

标签: python list duplicates

我有一份清单清单:

a = [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
     [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0],
     [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 5.0, 5.0, 5.0],
     [1.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0],
     [5.0, 5.0, 5.0], 
     [1.0]
    ]

a= set(a)

我需要做的是删除列表列表中的所有重复项并保留上一个序列。如

a = [[1.0],
     [2.0, 3.0, 4.0],
     [3.0, 5.0],
     [1.0, 4.0, 5.0],
     [5.0], 
     [1.0]
    ]

4 个答案:

答案 0 :(得分:3)

如果订单很重要,您只需与目前看到的项目集进行比较:

a = [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
     [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0],
     [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 5.0, 5.0, 5.0],
     [1.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0],
     [5.0, 5.0, 5.0], 
     [1.0]]

for index, lst in enumerate(a):
    seen = set()
    a[index] = [i for i in lst if i not in seen and seen.add(i) is None]

此处i作为副作用添加到seen,使用Python的惰性and评估;仅在第一次检查(seen.add(i))评估i not in seen时调用True

归因:我昨天从@timgeb 看到了这种技术。

答案 1 :(得分:2)

如果你有权访问OrderedDict(在Python 2.7中),滥用它是一个很好的方法:

import collections
import pprint

a = [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
     [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0],
     [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 5.0, 5.0, 5.0],
     [1.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0],
     [5.0, 5.0, 5.0], 
     [1.0]
    ]

b = [list(collections.OrderedDict.fromkeys(i)) for i in a]


pprint.pprint(b, width = 40)

输出:

[[1.0],
 [2.0, 3.0, 4.0],
 [3.0, 5.0],
 [1.0, 4.0, 5.0],
 [5.0],
 [1.0]]

答案 2 :(得分:0)

这会对你有帮助。

a = [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
 [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0],
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 5.0, 5.0, 5.0],
 [1.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0],
 [5.0, 5.0, 5.0], 
 [1.0]
]

for _ in range(len(a)):
    a[_] = sorted(list(set(a[_]))) 

print a

输出:

[[1.0], [2.0, 3.0, 4.0], [3.0, 5.0], [1.0, 4.0, 5.0], [5.0], [1.0]]

答案 3 :(得分:0)

受到DOSHI的启发,这是另一种方式,可能是少数可能元素的最佳方式(即排序的少量索引查找),否则记住插入顺序的方式可能更好:

b = [sorted(set(i), key=i.index) for i in a]

所以只是比较一下方法,一个看见的集合与原始索引查找对集合进行排序:

>>> setup = 'l = [1,2,3,4,1,2,3,4,1,2,3,4]*100'
>>> timeit.repeat('sorted(set(l), key=l.index)', setup)
[23.231241687943111, 23.302754517266294, 23.29650511717773]
>>> timeit.repeat('seen = set(); [i for i in l if i not in seen and seen.add(i) is None]', setup)
[49.855933579601697, 50.171151882997947, 51.024657420945005]

在这里我们看到,对于更大的情况,Jon对每个元素使用的包含测试变得相对非常昂贵,并且由于在这种情况下插入顺序很快由索引确定,因此这种方法更有效。

但是,通过在列表的末尾添加更多元素,我们看到Jon的方法不会带来太大的成本增加,而我的确如此:

>>> setup = 'l = [1,2,3,4,1,2,3,4,1,2,3,4]*100 + [8,7,6,5]'
>>> timeit.repeat('sorted(set(l), key=l.index)', setup)
[93.221347206941573, 93.013769266020972, 92.64512197257136]
>>> timeit.repeat('seen = set(); [i for i in l if i not in seen and seen.add(i) is None]', setup)
[51.042504915545578, 51.059295348750311, 50.979311841569142]

考虑到索引的查找时间不好,我认为我更喜欢Jon的方法和一个看见的集合。