首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何有效地基于共享项对对进行分组?

如何有效地基于共享项对对进行分组?
EN

Stack Overflow用户
提问于 2019-03-19 01:36:34
回答 5查看 2.7K关注 0票数 9

我有一个成对(元组)的列表,用于简化如下所示:

代码语言:javascript
复制
L = [("A","B"), ("B","C"), ("C","D"), ("E","F"), ("G","H"), ("H","I"), ("G","I"), ("G","J")]

使用python,我希望有效地将这个列表拆分为:

代码语言:javascript
复制
L1 = [("A","B"), ("B","C"), ("C","D")]
L2 = [("E","F")]
L3 = [("G","H"), ("G","I"), ("G","J"), ("H","I")]

如何有效地将列表分成两组,其中对于组中的对,必须始终至少有一对与他人共享一项?,如其中一个答案所述,这实际上是网络问题。其目标是有效地将网络拆分为断开(隔离)的网络部件。

类型列表、元组(组)可以更改以实现更高的效率。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2019-03-19 02:04:25

这更像是网络问题,所以我们可以使用networkx

代码语言:javascript
复制
import networkx as nx
G=nx.from_edgelist(L)

l=list(nx.connected_components(G))
# after that we create the map dict , for get the unique id for each nodes
mapdict={z:x for x, y in enumerate(l) for z in y }
# then append the id back to original data for groupby 
newlist=[ x+(mapdict[x[0]],)for  x in L]
import itertools
#using groupby make the same id into one sublist
newlist=sorted(newlist,key=lambda x : x[2])
yourlist=[list(y) for x , y in itertools.groupby(newlist,key=lambda x : x[2])]
yourlist
[[('A', 'B', 0), ('B', 'C', 0), ('C', 'D', 0)], [('E', 'F', 1)], [('G', 'H', 2), ('H', 'I', 2), ('G', 'I', 2), ('G', 'J', 2)]]

然后,要匹配输出格式:

代码语言:javascript
复制
L1,L2,L3=[[y[:2]for y in x] for x in yourlist]
L1
[('A', 'B'), ('B', 'C'), ('C', 'D')]
L2
[('E', 'F')]
L3
[('G', 'H'), ('H', 'I'), ('G', 'I'), ('G', 'J')]
票数 10
EN

Stack Overflow用户

发布于 2019-03-19 01:53:31

  • 将组列表初始化为空
  • (a, b)成为下一对
  • 收集所有包含有ab元素的组
  • 删除它们,加入它们,添加(a, b),并作为一个新组插入
  • 重复直到完成

会是这样的:

代码语言:javascript
复制
import itertools, functools

def partition(pred, iterable):
    t1, t2 = itertools.tee(iterable)
    return itertools.filterfalse(pred, t1), filter(pred, t2)

groups = []
for a, b in L:
    unrelated, related = partition(lambda group: any(aa == a or bb == b or aa == b or bb == a for aa, bb in group), groups)
    groups = [*unrelated, sum(related, [(a, b)])]
票数 2
EN

Stack Overflow用户

发布于 2019-03-19 03:22:37

一种高效的Pythonic方法是将元组列表转换为作为候选池的一组霜冻集,在while循环中,创建一个集合为组,并使用嵌套的while循环继续扩展组,方法是添加第一个候选集,然后与与该组相交的其他候选集执行set合并,直到没有更多的相交候选集合,此时返回到外部循环以形成一个新的组:

代码语言:javascript
复制
pool = set(map(frozenset, L))
groups = []
while pool:
    group = set()
    groups.append([])
    while True:
        for candidate in pool:
            if not group or group & candidate:
                group |= candidate
                groups[-1].append(tuple(candidate))
                pool.remove(candidate)
                break
        else:
            break

给定您的示例输入,groups将变成:

代码语言:javascript
复制
[[('A', 'B'), ('C', 'B'), ('C', 'D')],
 [('G', 'H'), ('H', 'I'), ('G', 'J'), ('G', 'I')],
 [('E', 'F')]]

请记住,集合在Python中是无序的,这就是为什么上述输出的顺序与预期的输出不匹配,但就您的目的而言,顺序应该无关紧要。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55232459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档