python迭代所有可能的序列(管网)

时间:2017-06-28 04:44:16

标签: python list

我有多个管道名称列表和相应的联结名称列表。

我还有两个包含上游和下游的列表 管道的连接处(To和From)。

例如

Pipes = [4000111858, 4000111839, 4000111848, 4000111871]

Junction = [4000068991, 4000068981, 4000069000, 4000069012, 4000237981]

From = [4000068991, 4000068981, 4000069000, 4000069012]

To = [4000069012, 4000068991, 4000069012, 4000237981]

我能够找到序列中的最后一个结点,因为它不会从列表(插座)中找到,然后从这里找到最后一个管道。

Outlet = []

Outlet_Pipe = []

for j in Junction:

    if j not in From:

        Outlet.append(j)

    for j, value in enumerate(Junction, -1):

        if value in Outlet:

            Outlet_Pipe.append(Pipes[j])

我需要构建从上游到下游的所有可能管道序列的列表(或多个列表)。 即:

[4000111839,4000111858, 4000111871] and [4000111848, 4000111871]

enter image description here

1 个答案:

答案 0 :(得分:0)

我的测试网络

我稍微调整了一下你的网络,看看我的代码如何对抗分叉

My network

import collections
import itertools

定义管道

Pipe = collections.namedtuple('Pipe', 'pipe start end')

all_pipes = [Pipe(pipe='A', start='a', end='d'),
             Pipe(pipe='B', start='b', end='a'),
             Pipe(pipe='C', start='c', end='d'),
             Pipe(pipe='D', start='d', end='e'),
             Pipe(pipe='E', start='d', end='f'),
            ]

如果您只有PipesFromTo的列表,则可以像这样创建该列表:

all_pipes = [Pipe(*pipe) for pipe in zip(Pipes, From, To)]

定义网络类

class PipeNetwork():
    def __init__(self, pipes):
        self.pipes = pipes
        names, start, end = list(zip(*pipes))
        self.junctions = set(start + end) # ['a', 'b', 'c', 'd', 'e', 'f']
        self.end_points = [k for k, v in collections.Counter(start + end).items() if v == 1]  
        # ['b', 'c', 'e', 'f']
        self.pipes_started = collections.defaultdict(set)
        self.pipes_ended = collections.defaultdict(set)
        for pipe in pipes:
            self.pipes_started[pipe.start].add(pipe)
            self.pipes_ended[pipe.end].add(pipe)

这是一个单向管道类。您需要对双向管道稍作调整

从给定起点找到可能路线的方法

检查从point开始在管道另一端开始的路径的所有管道

    def find_routes_from(self, point, route=None):
        # print(route)
        if route is None:
            route = [point]
        elif point in route:
            raise ValueError('circular route')
            # or `return None`
        else:
            route = route + [point]
        if point not in self.pipes_started:
            return [route] if len(route) > 1 else None
        # print(self.pipes_started[point])
        return [r for p in self.pipes_started[point] for r in self.find_routes_from(p.end, route) if r] 

查找所有路线

这会询问从所有端点开始的路径,这些端点有管道离开它们(返回一个可迭代的

    @property
    def all_routes(self):
        return itertools.chain().from_iterable(self.find_routes_from(p) for p in self.end_points if p in self.pipes_started)

调用一切

net = PipeNetwork(pipes=all_pipes)
list(net.all_routes)

产量

[['b', 'a', 'd', 'f'], ['b', 'a', 'd', 'e'], ['c', 'd', 'f'], ['c', 'd', 'e']]