根据Python中的条件对元素进行分组

时间:2019-01-07 04:58:21

标签: python list

我有一个线段的列表,每个线段的x和y坐标分别是其“从”和“到”点,如下所示(下面的示例被截断了,很长)。

[
{'f': {'x': 15.0, 'y': -5.0}, 't': {'x': 16.0, 'y': -5.0}},
{'f': {'x': 3.0, 'y': -7.0}, 't': {'x': 5.0, 'y': -7.0}},
{'f': {'x': 9.0, 'y': -7.0}, 't': {'x': 10.0, 'y': -7.0}},
{'f': {'x': 10.0, 'y': -4.0}, 't': {'x': 10.0, 'y': -5.0}},
{'f': {'x': 9.0, 'y': -4.0}, 't': {'x': 10.0, 'y': -4.0}},
{'f': {'x': 4.0, 'y': -4.0}, 't': {'x': 5.0, 'y': -4.0}},
...
]

我还有一个函数lines_connected,它将这些列表项(行)中的两个作为其ab参数,如果结束则返回True每条线的另一条线都在另一条线的一部分上(但False如果它们只是相交而一条线没有在另一条线的尽头,或者它们根本不“接触”)。使用此方法,我需要找到如上所述“连接”的所有行组(大概是列表中的列表)。并非组内的所有线路都必须直接与其他线路直接连接,而是通过组内的其他线路连接。

将这些行分组为这些“连接的组”的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

一种执行此操作的方法是使用基于网络的方法。您可以为此使用networkx

在此设置中,每个线段都是一个节点,lines_connected的输出将确定它们之间是否存在边。因此,如果lines_connectedab的任何两个段上显示True,则可以在两个节点之间创建边。否则你就没有了。

最后,您可以通过使用连接的子组件图来获得“连接的组”

import networkx as nx
#G would be your Node-Edge Graph created with line segments and the outuput of lines_connected 
sub_graphs = nx.connected_component_subgraphs(G)

答案 1 :(得分:1)

这是一个图形问题。您可以轻松地将列表转换为networkx图,端点为节点,线段为边:

import networkx as nx

def to_xy(p, key='f'):
    d = p[key]
    return (d['x'], d['y'])

segments = [...]
g = nx.Graph()
for seg in segments:
    g.add_edge(to_xy(seg, 'f'), to_xy(seg, 't'), obj=seg)

作为参考,我在每个边上添加了一个obj属性,该属性指向用于构造它的原始字典。

现在要获取组,您要做的就是获取图形的connected components:每个组件内的边将是相互连接的线段。这些可以根据不推荐使用的connected_component_subgraphs方法的描述获得:

components = map(g.subgraph, nx.connected_components(g))
edges = [list(nx.get_edge_attributes(sg, 'obj').values()) for sg in components]

要检查是否以某种方式连接了两个点,只需检查从一个起点到另一个起点之间是否有path,例如here

nx.has_path(g, to_xy(s1), to_xy(s2))

对于端点使用f还是t都没关系。