我有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]
]
答案 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])]