在python中跨多个列表删除公共列表元素的最简洁方法

时间:2012-03-05 23:01:20

标签: python list set

我有n个数字列表。我想确保每个列表包含该特定列表的唯一元素。即其余任何一个都没有“共享”重复 这对于两个列表来说非常容易,但是对于n个列表来说有点棘手。

e.g.   
mylist = [
[1, 2, 3, 4],
[2, 5, 6, 7],
[4, 2, 8, 9]
]

变为:

mylist = [
[1, 3],
[5, 6, 7],
[8, 9]
]

5 个答案:

答案 0 :(得分:5)

from collections import Counter
from itertools import chain

mylist = [
    [1,2,3,4],
    [2,5,6,7,7],
    [4,2,8,9]
]

counts = Counter(chain(*map(set,mylist)))

[[i for i in sublist if counts[i]==1] for sublist in mylist]
#[[1, 3], [5, 6, 7, 7], [8, 9]]

答案 1 :(得分:2)

这是线性时间,2次传球。我假设你想在列表中保留重复项;如果没有,这可以简化一下:

>>> import collections, itertools
>>> counts = collections.defaultdict(int)
>>> for i in itertools.chain.from_iterable(set(l) for l in mylist):
...     counts[i] += 1
... 
>>> for l in mylist:
...     l[:] = (i for i in l if counts[i] == 1)
... 
>>> mylist
[[1, 3], [5, 6, 7], [8, 9]]

答案 2 :(得分:1)

由于您不关心订单,因此您可以使用set subtraction轻松删除重复项并转换回列表。这是一个怪物单行:

>>> mylist = [
... [1, 2, 3, 4],
... [2, 5, 6, 7],
... [4, 2, 8, 9]
... ]
>>> mynewlist = [list(set(thislist) - set(element for sublist in mylist for element in sublist if sublist is not thislist)) for thislist in mylist]
>>> mynewlist
[[1, 3], [5, 6, 7], [8, 9]]

注意: 这不是很有效,因为每行重新计算重复项。这是否有问题取决于您的数据大小。

答案 3 :(得分:0)

set()是正确的方法。 虽然你不必使用列表理解。

没有额外的进口:

mylist = [
[1, 2, 3, 4],
[2, 5, 6, 7],
[4, 2, 8, 9]
]
>>> result_list = []
>>> for test_list in mylist:
...     result_set = set(test_list)
...     for compare_list in mylist:
...         if test_list != compare_list:
...             result_set = result_set - set(compare_list)
...     result_list.append(result_set)
...
>>> result_list
[set([1, 3]), set([5, 6, 7]), set([8, 9])]

答案 4 :(得分:0)

这是我的解决方案,使用Counter构建一组所有常用数字,然后它只是设置差异:

from collections import Counter

def disjoin(lsts):
    c = Counter(num for lst in lsts for num in lst)
    common = set(x for x,v in c.items() if v > 1)
    result = []
    for lst in lsts:
        result.append(set(lst) - common)
    return result

示例:

>>> remove_common(mylist)
[set([1, 3]), set([5, 6, 7]), set([8, 9])]