列表的 Python 生成器对象生成的列表太大。如何限制输出大小

问题描述 投票:0回答:1

四色定理指出,对于连通图,任何节点都可以着色,使得相邻节点不共享相同的颜色,并且对于任何图,都有一个需要不超过四种颜色的解决方案。

我在堆栈溢出上找到了满足四色定理的Python代码,并且我已合并该代码来处理地理空间数据,这样共享边界的两个多边形不会共享相同的颜色。我找到的四色定理代码返回一个 Python 生成器对象(我对生成器不熟悉),并将这个生成器对象转换为 Python 列表以进行进一步处理。这在我的几个多边形的测试数据上运行良好且快速。由于四色定理有不止一种解决方案,因此我筛选了可能的解决方案(从生成器创建的列表),并找到具有最均匀颜色分布的解决方案,以获得最好的制图效果。

现在代码可以运行了,我在美国 50 个多边形测试数据集上对其进行了测试。问题是,四色定理有太多的解决方案,导致要列出的生成器太大,以至于导致我的 IDE 崩溃。我假设我可以将可能的解决方案限制为几千个解决方案,并在那几千个解决方案中找到具有良好颜色分布的合适解决方案。

如何限制从生成器返回的列表项的数量?

下面是返回生成器的函数。这个函数的工作原理和生成器对象超出了我的技能水平。我确实知道如何限制函数中或转换为列表时的解决方案(或列表项)的数量。

    def colour_map(nodes, edges, ncolours=4):
        colours = range(ncolours)
        #The edges that meet each node
        node_edges = dict((n, set()) for n in nodes)
        for e in edges:
            n0, n1 = e
            node_edges[n0].add(e)
            node_edges[n1].add(e)

        for n in nodes:
            node_edges[n] = list(node_edges[n])
        #Set to cover
        coloured_edges = list(product(colours, edges))
        X = nodes + coloured_edges
        #Subsets to cover X with
        Y = dict()
        #Primary rows
        for n in nodes:
            ne = node_edges[n]
            for c in colours:
                Y[(n, c)] = [n] + [(c, e) for e in ne]
        #Dummy rows
        for i, ce in enumerate(coloured_edges):
            Y[i] = [ce]
        X = exact_cover(X, Y)
        #Set first two nodes
        partial = [(nodes[0], 0), (nodes[1], 1)]
        for s in partial:
            select(X, Y, s)
        for s in solve(X, Y, []):
            s = partial + [u for u in s if not isinstance(u, int)]
            s.sort()
            yield s
    #call the color map function to get the generator object...
    all_solutions = colour_map(nodes, adjacent_polygons_graph, ncolours=3)

   #convert the generator object to a list
    solution_list = list(all_solutions)

我尝试按照建议限制产量数量,但这会返回一个空的生成器。

    yield_counter = 0
    for s in solve(X, Y, []):
        yield_counter +=1
        s = partial + [u for u in s if not isinstance(u, int)]
        s.sort()
        yield s
        if yield_counter == 100:
            break           
python list generator
1个回答
0
投票

如果您想保留该方法来产生结果并将其留给调用者来确定他们何时“足够”,您可以这样做:

def foo():
    while True:
        yield "hi"

results = foo()
for _ in range(10):
    print(next(results))

## or

results = foo()
print([next(results) for _ in range(10)])

也许是这样的:

all_solutions = colour_map(nodes, adjacent_polygons_graph, ncolours=3)
for _ in range(10):
    solution = next(all_solutions)
    ## do something with this solution

all_solutions = colour_map(nodes, adjacent_polygons_graph, ncolours=3)
enough_solutions = [next(all_solutions) for _ in range(10)]
## do something with this first 10 solutions

请注意,这种模式可能需要您防范

StopIteration
,但只要您确定消耗的量少于可能产生的量,就应该没问题。

© www.soinside.com 2019 - 2024. All rights reserved.