使用递归避免写嵌套循环数等于层数? [英] Use recursion to avoid writing nested loop number equal to the number of layers?

查看:36
本文介绍了使用递归避免写嵌套循环数等于层数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将 numpy 导入为 np导入 matplotlib.pyplot 作为 plt将 matplotlib.lines 作为行导入类 DG():def __init__(self, name):self.dgs = []self.name = str(name)def add_dg(self, name):dg = DG(姓名=姓名)self.dgs.append(dg)返回 dgdef __repr__(self):return ('{self.name}'.format(self=self))def find_trees(self):# https://stackoverflow.com/questions/60339232/return-a-list-of-all-objects-vertically-stacked-above-a-given-object# https://en.wikipedia.org/wiki/Tree_traversalself.trees = []def __fill_dg_trees(dg_trees, dg, 路径):对于 dg.dgs 中的 th:__fill_dg_trees(dg_trees, th, path + [dg])如果不是 dg.dgs:self.trees.append(path + [dg])__fill_dg_trees(self.trees, self, [])self.n_trees = len(self.trees)类子():def __init__(self, name):self.width = 1.0自我.x0 = 0.0self.name = 姓名self.dgs = []def add_dg(self, name):dg = DG(姓名=姓名)self.dgs.append(dg)返回 dgdef find_trees(self):# https://stackoverflow.com/questions/60339232/return-a-list-of-all-objects-vertically-stacked-above-a-given-object# https://en.wikipedia.org/wiki/Tree_traversalself.trees = []def __fill_dg_trees(dg_trees, dg, 路径):对于 dg.dgs 中的 th:__fill_dg_trees(dg_trees, th, path + [dg])如果不是 dg.dgs:self.trees.append(path + [dg])__fill_dg_trees(self.trees, self, [])self.n_trees = len(self.trees)def __repr__(self):return ('{self.name}'.format(self=self))# -----------# |C |D |# -----------------------------# |乙 |F |G |H |# -----------------------------# |一个 |E |# -----------------------------# |基材 |# -----------------------------sub = Sub(name='My Substrate')A = sub.add_dg(name='A')B = A.add_dg(name='B')C = B.add_dg(name='C')D = B.add_dg(name='D')E = sub.add_dg('E')F = E.add_dg('F')G = E.add_dg('G')H = E.add_dg('H')sub.find_trees()sub.goodies = set(sum(sub.trees, [])).difference(set([sub]))对于 sub.goodies 中的东西:thing.find_trees()sub.tree_height = max([len(tree) for tree in sub.trees]) - 1sub.n_trees = len(sub.trees)sub.n_goodies = len(sub.goodies)打印('sub.tree_height:',sub.tree_height)打印('sub.n_trees:',sub.n_trees)打印('sub.n_goodies:',sub.n_goodies)打印('sub.goodies:',sub.goodies)对于我,枚举中的树(sub.trees):打印(我,树)def squareit(东西, nh, dh, dd, hw, hh):x0 = 事物.x0linez, 文本 = [], []打印('被称为事物:',事物)打印('thing.width,thing.n_trees:',thing.width,thing.n_trees)对于 i, dg in enumerate(thing.dgs):打印('我,dg:',我,dg)打印('dg.n_trees:',dg.n_trees)dg.width = float(dg.n_trees) * thing.width/thing.n_treesdg.x0 = x0打印('dg.width:',dg.width)x1, x2 = x0+dd, x0 + dg.width - ddy1, y2 = nh*dh + dd, ((nh+1)*dh) - ddxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])轮廓=lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,变换=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-ddtexts.append((xt, yt, dg.name))x1, x2 = x0 + 0.5*dg.width - hw, x0 + 0.5*dg.width + hwy1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hhxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,变换=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031linez += [轮廓,control_pannel_line]x0 += dg.width返回 linez, 文本如果属实:fig = plt.figure()x0 = 0.dd = 0.01dh = 0.2hw, hh = 0.05, 0.075# linez, texts = [], []# 先绘制基板nh = 0x1, x2 = x0+dd, x0 + sub.width - ddy1, y2 = nh*dh + dd, ((nh+1)*dh) - ddxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])轮廓=lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,变换=fig.transFigure,图=无花果)xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-dd文本 = [(xt, yt, sub.name)]x1, x2 = x0 + 0.5*sub.width - hw, x0 + 0.5*sub.width + hwy1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hhxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,变换=fig.transFigure,图=无花果)linez = [大纲,control_pannel_line]# 现在遍历整个事情# 第一层:a, b = squareit(sub, nh=1, dh=dh, dd=dd, hw=hw, hh=hh)线 += 一个文本 += b# 第二层:对于 sub.dgs 中的 dg:a, b = squareit(dg, nh=2, dh=dh, dd=dd, hw=hw, hh=hh)线 += 一个文本 += b# 第三层:对于 dg.dgs 中的 dgg:a, b = squareit(dgg, nh=3, dh=dh, dd=dd, hw=hw, hh=hh)线 += 一个文本 += bfig.lines.extend(linez) # https://matplotlib.org/3.1.0/gallery/pyplots/fig_x.htmlfor (x, y, text) 在文本中:fig.text(x, y, text, fontsize=14)plt.show()

解决方案

我使用 dfs 并且只使用一个类 Sub(因为我认为 Sub 和 DG 是多余的).代码如下:

将 numpy 导入为 np导入 matplotlib.pyplot 作为 plt将 matplotlib.lines 作为行导入类子():def __init__(self, name):self.width = 1.0自我.x0 = 0.0self.name = 姓名self.dgs = []def add_dg(self, name):dg = 子(名称=名称)self.dgs.append(dg)返回 dgdef find_trees(self):# https://stackoverflow.com/questions/60339232/return-a-list-of-all-objects-vertically-stacked-above-a-given-object# https://en.wikipedia.org/wiki/Tree_traversalself.trees = []def __fill_dg_trees(dg_trees, dg, 路径):对于 dg.dgs 中的 th:__fill_dg_trees(dg_trees, th, path + [dg])如果不是 dg.dgs:self.trees.append(path + [dg])__fill_dg_trees(self.trees, self, [])self.n_trees = len(self.trees)def __repr__(self):return ('{self.name}'.format(self=self))# -----------# |C |D |# -----------------------------# |乙 |F |G |H |# -----------------------------# |一个 |E |# -----------------------------# |基材 |# -----------------------------sub = Sub(name='My Substrate')A = sub.add_dg(name='A')B = A.add_dg(name='B')C = B.add_dg(name='C')D = B.add_dg(name='D')E = sub.add_dg('E')F = E.add_dg('F')G = E.add_dg('G')H = E.add_dg('H')sub.find_trees()sub.goodies = set(sum(sub.trees, [])).difference(set([sub]))对于 sub.goodies 中的东西:thing.find_trees()sub.tree_height = max([len(tree) for tree in sub.trees]) - 1sub.n_trees = len(sub.trees)sub.n_goodies = len(sub.goodies)打印('sub.tree_height:',sub.tree_height)打印('sub.n_trees:',sub.n_trees)打印('sub.n_goodies:',sub.n_goodies)打印('sub.goodies:',sub.goodies)对于我,枚举中的树(sub.trees):打印(我,树)def squareit(东西, nh, dh, dd, hw, hh):x0 = 事物.x0linez, 文本 = [], []打印('被称为事物:',事物)打印('thing.width,thing.n_trees:',thing.width,thing.n_trees)对于 i, dg in enumerate(thing.dgs):打印('我,dg:',我,dg)打印('dg.n_trees:',dg.n_trees)dg.width = float(dg.n_trees) * thing.width/thing.n_treesdg.x0 = x0打印('dg.width:',dg.width)x1, x2 = x0+dd, x0 + dg.width - ddy1, y2 = nh*dh + dd, ((nh+1)*dh) - ddxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])轮廓=lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,变换=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-ddtexts.append((xt, yt, dg.name))x1, x2 = x0 + 0.5*dg.width - hw, x0 + 0.5*dg.width + hwy1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hhxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,变换=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031linez += [轮廓,control_pannel_line]x0 += dg.width返回 linez, 文本如果属实:fig = plt.figure()x0 = 0.dd = 0.01dh = 0.2hw, hh = 0.05, 0.075# linez, texts = [], []# 先绘制基板nh = 0x1, x2 = x0+dd, x0 + sub.width - ddy1, y2 = nh*dh + dd, ((nh+1)*dh) - ddxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])轮廓=lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,变换=fig.transFigure,图=无花果)xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-dd文本 = [(xt, yt, sub.name)]x1, x2 = x0 + 0.5*sub.width - hw, x0 + 0.5*sub.width + hwy1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hhxx = np.array([x1, x2, x2, x1, x1])yy = np.array([y1, y1, y2, y2, y1])control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,变换=fig.transFigure,图=无花果)linez = [大纲,control_pannel_line]# 使用 DFS:def dfs(node, nh, linez, texts):a, b = squareit(node, nh=nh, dh=dh, dd=dd, hw=hw, hh=hh)线 += 一个文本 += b对于 node.dgs 中的孩子:dfs(child, nh+1, linez, texts)dfs(sub, nh=1, linez=linez, texts=texts)fig.lines.extend(linez) # https://matplotlib.org/3.1.0/gallery/pyplots/fig_x.htmlfor (x, y, text) 在文本中:fig.text(x, y, text, fontsize=14)plt.show()

注意注释# Using DFS的部分.

我已经在我的 jupyter 上尝试过,似乎输出与您的代码相同的内容.希望这有帮助!

This excellent answer to Return a list of all objects vertically stacked above a given object? started me on tree traversal, now I need to start building a complex control panel using wxPython.

I'm learning about sizers but for this abstracted script I've used matplotlib to generate what the panel will look like.

The part I need help with is only the bit near the end with the comments First layer, Second layer and Third layer. What I need is to use recursion so that I don't have to have the correct number of nested loops equal to the number of layers.

Once I get better at wxPython I'll use the same recursion to build the real control panel.

Each heavy black rectangle will ultimately be a cluster of wxPython widgets, and each thing red rectangle will be the enclosing sizer.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as lines

class DG():
    def __init__(self, name):

        self.dgs = []
        self.name = str(name)

    def add_dg(self, name):
        dg = DG(name=name)
        self.dgs.append(dg)
        return dg

    def __repr__(self):
        return ('{self.name}'.format(self=self))

    def find_trees(self):
        # https://stackoverflow.com/questions/60339232/return-a-list-of-all-objects-vertically-stacked-above-a-given-object
        # https://en.wikipedia.org/wiki/Tree_traversal
        self.trees = []
        def __fill_dg_trees(dg_trees, dg, path):
            for th in dg.dgs:
                __fill_dg_trees(dg_trees, th, path + [dg])
            if not dg.dgs:
                self.trees.append(path + [dg])
        __fill_dg_trees(self.trees, self, [])
        self.n_trees = len(self.trees)

class Sub():
    def __init__(self, name):
        self.width = 1.0 
        self.x0 = 0.0 
        self.name = name
        self.dgs = []

    def add_dg(self, name):
        dg = DG(name=name)
        self.dgs.append(dg)
        return dg

    def find_trees(self):
        # https://stackoverflow.com/questions/60339232/return-a-list-of-all-objects-vertically-stacked-above-a-given-object
        # https://en.wikipedia.org/wiki/Tree_traversal
        self.trees = []
        def __fill_dg_trees(dg_trees, dg, path):
            for th in dg.dgs:
                __fill_dg_trees(dg_trees, th, path + [dg])
            if not dg.dgs:
                self.trees.append(path + [dg])
        __fill_dg_trees(self.trees, self, [])
        self.n_trees = len(self.trees)

    def __repr__(self):
        return ('{self.name}'.format(self=self))

#  -----------
# |  C  |  D  |
#  -----------------------------
# |      B    |  F  |  G  |  H  |
#  -----------------------------
# |      A    |     E           |
#  -----------------------------
# |       Substrate             |
#  -----------------------------

sub = Sub(name='My Substrate')
A = sub.add_dg(name='A')
B = A.add_dg(name='B')
C = B.add_dg(name='C')
D = B.add_dg(name='D')
E = sub.add_dg('E')
F = E.add_dg('F')
G = E.add_dg('G')
H = E.add_dg('H')

sub.find_trees()
sub.goodies = set(sum(sub.trees, [])).difference(set([sub]))
for thing in sub.goodies:
    thing.find_trees()
sub.tree_height = max([len(tree) for tree in sub.trees]) - 1
sub.n_trees = len(sub.trees)
sub.n_goodies = len(sub.goodies)
print('sub.tree_height: ', sub.tree_height)
print('sub.n_trees: ', sub.n_trees)
print('sub.n_goodies: ', sub.n_goodies)
print('sub.goodies: ', sub.goodies)

for i, tree in enumerate(sub.trees):
    print(i, tree)

def squareit(thing, nh, dh, dd, hw, hh):
    x0 = thing.x0
    linez, texts = [], []
    print('called thing: ', thing)
    print('thing.width, thing.n_trees: ', thing.width, thing.n_trees)
    for i, dg in enumerate(thing.dgs):
        print('i, dg: ', i, dg)
        print('dg.n_trees: ', dg.n_trees)
        dg.width = float(dg.n_trees) * thing.width / thing.n_trees
        dg.x0 = x0
        print('dg.width: ', dg.width)
        x1, x2 = x0+dd, x0 + dg.width - dd
        y1, y2 = nh*dh + dd, ((nh+1)*dh) - dd
        xx = np.array([x1, x2, x2, x1, x1])
        yy = np.array([y1, y1, y2, y2, y1])
        outline = lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,
                              transform=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031
        xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-dd
        texts.append((xt, yt, dg.name))

        x1, x2 = x0 + 0.5*dg.width - hw, x0 + 0.5*dg.width + hw
        y1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hh
        xx = np.array([x1, x2, x2, x1, x1])
        yy = np.array([y1, y1, y2, y2, y1])
        control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,
                              transform=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031
        linez += [outline, control_pannel_line]
        x0 += dg.width
    return linez, texts

if True:
    fig = plt.figure()
    x0 = 0.
    dd = 0.01
    dh = 0.2
    hw, hh = 0.05, 0.075
    # linez, texts = [], []

    # draw the substrate first
    nh = 0
    x1, x2 = x0+dd, x0 + sub.width - dd
    y1, y2 = nh*dh + dd, ((nh+1)*dh) - dd
    xx = np.array([x1, x2, x2, x1, x1])
    yy = np.array([y1, y1, y2, y2, y1])
    outline = lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,
                          transform=fig.transFigure, figure=fig)

    xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-dd
    texts = [(xt, yt, sub.name)]

    x1, x2 = x0 + 0.5*sub.width - hw, x0 + 0.5*sub.width + hw
    y1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hh
    xx = np.array([x1, x2, x2, x1, x1])
    yy = np.array([y1, y1, y2, y2, y1])
    control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,
                          transform=fig.transFigure, figure=fig)
    linez = [outline, control_pannel_line]

    # now iterate through the whole thing

    # first layer:    
    a, b = squareit(sub, nh=1, dh=dh, dd=dd, hw=hw, hh=hh)
    linez += a
    texts += b

    # second layer:    
    for dg in sub.dgs:
        a, b = squareit(dg, nh=2, dh=dh, dd=dd, hw=hw, hh=hh)
        linez += a
        texts += b

        # third layer:    
        for dgg in dg.dgs:
            a, b = squareit(dgg, nh=3, dh=dh, dd=dd, hw=hw, hh=hh)
            linez += a
            texts += b

    fig.lines.extend(linez) # https://matplotlib.org/3.1.0/gallery/pyplots/fig_x.html

    for (x, y, text) in texts:
        fig.text(x, y, text, fontsize=14)
    plt.show()

解决方案

I use dfs and only use one class Sub (since I think Sub and DG is redundant). Here is the code:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as lines

class Sub():
    def __init__(self, name):
        self.width = 1.0 
        self.x0 = 0.0 
        self.name = name
        self.dgs = []

    def add_dg(self, name):
        dg = Sub(name=name)
        self.dgs.append(dg)
        return dg

    def find_trees(self):
        # https://stackoverflow.com/questions/60339232/return-a-list-of-all-objects-vertically-stacked-above-a-given-object
        # https://en.wikipedia.org/wiki/Tree_traversal
        self.trees = []
        def __fill_dg_trees(dg_trees, dg, path):
            for th in dg.dgs:
                __fill_dg_trees(dg_trees, th, path + [dg])
            if not dg.dgs:
                self.trees.append(path + [dg])
        __fill_dg_trees(self.trees, self, [])
        self.n_trees = len(self.trees)

    def __repr__(self):
        return ('{self.name}'.format(self=self))

#  -----------
# |  C  |  D  |
#  -----------------------------
# |      B    |  F  |  G  |  H  |
#  -----------------------------
# |      A    |     E           |
#  -----------------------------
# |       Substrate             |
#  -----------------------------

sub = Sub(name='My Substrate')
A = sub.add_dg(name='A')
B = A.add_dg(name='B')
C = B.add_dg(name='C')
D = B.add_dg(name='D')
E = sub.add_dg('E')
F = E.add_dg('F')
G = E.add_dg('G')
H = E.add_dg('H')

sub.find_trees()
sub.goodies = set(sum(sub.trees, [])).difference(set([sub]))
for thing in sub.goodies:
    thing.find_trees()
sub.tree_height = max([len(tree) for tree in sub.trees]) - 1
sub.n_trees = len(sub.trees)
sub.n_goodies = len(sub.goodies)
print('sub.tree_height: ', sub.tree_height)
print('sub.n_trees: ', sub.n_trees)
print('sub.n_goodies: ', sub.n_goodies)
print('sub.goodies: ', sub.goodies)

for i, tree in enumerate(sub.trees):
    print(i, tree)

def squareit(thing, nh, dh, dd, hw, hh):
    x0 = thing.x0
    linez, texts = [], []
    print('called thing: ', thing)
    print('thing.width, thing.n_trees: ', thing.width, thing.n_trees)
    for i, dg in enumerate(thing.dgs):
        print('i, dg: ', i, dg)
        print('dg.n_trees: ', dg.n_trees)
        dg.width = float(dg.n_trees) * thing.width / thing.n_trees
        dg.x0 = x0
        print('dg.width: ', dg.width)
        x1, x2 = x0+dd, x0 + dg.width - dd
        y1, y2 = nh*dh + dd, ((nh+1)*dh) - dd
        xx = np.array([x1, x2, x2, x1, x1])
        yy = np.array([y1, y1, y2, y2, y1])
        outline = lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,
                              transform=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031
        xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-dd
        texts.append((xt, yt, dg.name))

        x1, x2 = x0 + 0.5*dg.width - hw, x0 + 0.5*dg.width + hw
        y1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hh
        xx = np.array([x1, x2, x2, x1, x1])
        yy = np.array([y1, y1, y2, y2, y1])
        control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,
                              transform=fig.transFigure, figure=fig) # https://stackoverflow.com/a/5022412/3904031
        linez += [outline, control_pannel_line]
        x0 += dg.width
    return linez, texts

if True:
    fig = plt.figure()
    x0 = 0.
    dd = 0.01
    dh = 0.2
    hw, hh = 0.05, 0.075
    # linez, texts = [], []

    # draw the substrate first
    nh = 0
    x1, x2 = x0+dd, x0 + sub.width - dd
    y1, y2 = nh*dh + dd, ((nh+1)*dh) - dd
    xx = np.array([x1, x2, x2, x1, x1])
    yy = np.array([y1, y1, y2, y2, y1])
    outline = lines.Line2D(xx, yy, lw=1., color='r', alpha=1.0,
                          transform=fig.transFigure, figure=fig)

    xt, yt = x0+1.5*dd, ((nh+0.5)*dh)-dd
    texts = [(xt, yt, sub.name)]

    x1, x2 = x0 + 0.5*sub.width - hw, x0 + 0.5*sub.width + hw
    y1, y2 = ((nh+0.5)*dh) - hh, ((nh+0.5)*dh) + hh
    xx = np.array([x1, x2, x2, x1, x1])
    yy = np.array([y1, y1, y2, y2, y1])
    control_pannel_line = lines.Line2D(xx, yy, lw=3., color='k', alpha=1.0,
                          transform=fig.transFigure, figure=fig)
    linez = [outline, control_pannel_line]

    # Using DFS:
    def dfs(node, nh, linez, texts):
        a, b = squareit(node, nh=nh, dh=dh, dd=dd, hw=hw, hh=hh)
        linez += a
        texts += b
        for child in node.dgs:
            dfs(child, nh+1, linez, texts)
    dfs(sub, nh=1, linez=linez, texts=texts)

    fig.lines.extend(linez) # https://matplotlib.org/3.1.0/gallery/pyplots/fig_x.html

    for (x, y, text) in texts:
        fig.text(x, y, text, fontsize=14)
    plt.show()

Notice the part with comment # Using DFS.

I have tried it on my jupyter and seems to output the same thing as your code. Hope this help!

这篇关于使用递归避免写嵌套循环数等于层数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆