経緯
・以下のような階層構造ツリーを作りたい。
入力:
[0,1,2,2,2,3,2,2,3,2,3,4,4,5,5,4,4,5,4,4,1,1,1,2,1,1,1]
出力:
┬────
├┬───
│├───
│├───
│├┬──
││└──
│├───
│├┬──
││└──
│└┬──
│ └┬─
│ ├─
│ ├┬
│ │├
│ │└
│ ├─
│ ├┬
│ │└
│ ├─
│ └─
├────
├────
├┬───
│└───
├────
├────
└────
・階層構造ツリーを作成する関連で調べても、ディレクトリ風のテキストを作るものしか出てこない
⇒自分で作りました。
結論
とりあえずpythonで記載
code1.py
def generate_tree(depths):
"""
depths: list of non-negative整数。最初の要素は0で、それ以降に0は出てこないものとする。
戻り値: 各行を表す罫線ツリーの文字列リスト。
"""
# 入力チェック
if len(depths) < 2:
raise ValueError("入力は2行以上必要です")
if depths[0] != 0 or any(d == 0 for d in depths[1:]):
raise ValueError("1行目のみ0、それ以降に0は許されません")
max_depth = max(depths)
V, H, S = '│', '─', ' ' # 縦線, 横線, 全角スペース
T, TEE, ELB = '┬', '├', '└'
n = len(depths)
lines = []
for i, d in enumerate(depths):
# 子ノード判定
has_child = (i+1 < n and depths[i+1] > d)
# 兄弟ノード判定
has_sibling = False
for j in range(i+1, n):
if depths[j] < d:
break
if depths[j] == d:
has_sibling = True
break
row = []
for pos in range(max_depth):
if pos < d-1:
# ── 祖先レベルの縦線判定 ──
# 後続行を順に見て、
# ・depths[j] < pos+1 → その祖先ブランチは終了 → 縦線なし
# ・depths[j] > pos → まだそのブランチに子孫あり → 縦線あり
# ・depths[j] == pos+1 → 同じレベルの子や孫 → 縦線あり
# のいずれかで判定を打ち切る
draw_v = False
for j in range(i+1, n):
if depths[j] < pos+1:
# 祖先レベル pos はもう続かない
break
elif depths[j] == pos+1:
# depths[j] >= pos の間は縦線を引く
draw_v = True
break
row.append(V if draw_v else S)
elif pos == d-1:
# 親からの分岐 ├ または └
row.append(TEE if has_sibling else ELB)
elif pos == d:
# 自分自身の分岐 ┬(子あり)/─(子なし)
row.append(T if has_child else H)
else:
# それ以降は横線で埋める
row.append(H)
lines.append(''.join(row))
return lines
if __name__ == "__main__":
# テスト用サンプル
sample = [0,1,2,2,2,3,2,2,3,2,3,4,4,5,5,4,4,5,4,4,1,1,1,2,1,1,1]
for line in generate_tree(sample):
print(line)
関数として記載しています。
これを適宜、自分のツールに組み込みましょう