使用递归避免写嵌套循环数等于层数? [英] Use recursion to avoid writing nested loop number equal to the number of layers?
问题描述
将 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屋!