我有一个列表列表,其中每个子列表包含一些整数:
o = [[1,2],[3,4],[2,3],[5,4]]
我想创建一个新的列表列表,其中o
中共享公共成员的任何两个子列表将被合并。这个合并过程应该继续,直到没有两个子列表共享一个共同的元素。鉴于o
,我们会将[1,2]
与[2,3]
合并,因为它们共享2,然后我们将该组与[3,4]
合并,因为[1,2,3]
和{ {1}}都包含3,依此类推。
群集[3,4]
的预期输出为o
我有预感,这项任务的方法远远优于我目前的方法(见下文)。任何其他人可以提供的最有效(时间,空间)方式的建议将非常感激。
[[1,2,3,4,5]]
答案 0 :(得分:2)
from collections import deque
o = [[1,2],[3,4],[2,3],[5,4], [10, 11, 12], [13, 15], [4,6], [6, 8], [23,25]]
o = sorted(o, key=lambda x:min(x))
queue = deque(o)
grouped = []
while len(queue) >= 2:
l1 = queue.popleft()
l2 = queue.popleft()
s1 = set(l1)
s2 = set(l2)
if s1 & s2:
queue.appendleft(s1 | s2)
else:
grouped.append(s1)
queue.appendleft(s2)
# print(set(l1).union(set(l2)))
if queue:
grouped.append(queue.pop())
print(grouped)
<强>输出强>
[set([1, 2, 3, 4, 5, 6, 8]), set([10, 11, 12]), set([13, 15]), set([25, 23])]
答案 1 :(得分:0)
您可以使用递归:
def cluster(d, current = []):
options = [i for i in d if any(c in current for c in i)]
_flattened = [i for b in options for i in b]
d = list(filter(lambda x:x not in options, d))
if not options or not d:
yield current+_flattened
if d and not options:
yield from cluster(d[1:], d[0])
elif d:
yield from cluster(d, current+_flattened)
for a, *b in [[[1,2],[6,4],[2,3],[5,4]], [[1,2],[3,4],[2,3],[5,4]], [[1,2],[3,4],[2,3],[5,4], [10, 11, 12], [13, 15], [4,6], [6, 8], [23,25]]]:
print([list(set(i)) for i in cluster(b, a)])
输出:
[[1, 2, 3], [4, 5, 6]]
[[1, 2, 3, 4, 5]]
[[1, 2, 3, 4, 5, 6, 8], [10, 11, 12], [13, 15], [25, 23]]