将多维元组显示为树的Python解决方案

2024-04-27 12:03:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我想通过使用Unicode字体中存在的一组图形符号(例如.\u2500、\u2502、\u2514和其他字体)来显示多维元组中包含的树状结构。下面是我所说的输出类型的一个示例:

>>> show_tree('(01, (02,  03, 04), 05, ((06, 07), 08), (09, (10, 11), (12, 13), 14), 15)')
┬─01
├─┬─02
│ ├─03
│ └─04
├─05
├─┬─┬─06
│ │ └─07
│ └─08
├─┬─09
│ ├─┬─10
│ │ └─11
│ ├─┬─12
│ │ └─13
│ └─14
└─15

理想情况下,应正确管理空项、多字项、逗号或括号周围的额外空格以及不平衡括号,如以下示例所示:

>>> show_tree('( A, B multi-word item , (C,D), ( E  , ,  F ), G  )'))
┬─A
├─B multi-word item
├─┬─C
│ └─D
├─┬─E
│ ├─
│ └─F
└─G

我提出了一个很好的解决方案(上面的例子就是用它生成的),但是实现的算法不是很优雅,代码也不是很pythonic:

def show_tree(string):
    """display multidimensional tuple as a tree"""
    glyphs = ['\u252C\u2500','\u251C\u2500','\u2514\u2500','\u2502 ']
    tree, glyph, item = [], [], []
    for char in string:                                             # loop over chars in provided string
        if char in ',)' and item:                                   # add glyph prefix and current item to tree
            tree.append(glyph + [''.join(item).strip()]); item = []
        if char == ',':                                             # update glyph prefix for new item in sublist
            glyph = [glyphs[3]] * (len(glyph)-1) + [glyphs[1]]
        elif char == ')':                                           # update glyph prefix for last item in sublist
            tree[-1][-2] = glyphs[2]; glyph = glyph[:-1] 
        elif char == '(':                                           # update glyph prefix for first item in sublist
            glyph.append(glyphs[0])
        else:                                                       # other chars are simply added to current item
            item.append(char)
    return '\n'.join(''.join(node) for node in tree)

因此,我想了解一些改进实现的想法,可能使用正则表达式或其他高级解析技术。非常感谢您的任何提示


Tags: intreeforstringprefixshowupdateitem
1条回答
网友
1楼 · 发布于 2024-04-27 12:03:23

根据@KyleL的建议,我将我的问题发布到codereview.stackexchange.com,并通过@Peilonrayz获得了一个非常优雅的解决方案。完整的答案是here,但如果有人感兴趣,我只需将他的代码粘贴到下面:

def show_tree(root):
    return '\n'.join(build_tree(root))

def build_tree(node):
    if not isinstance(node, tuple):
        yield str(node)
        return

    values = [build_tree(n) for n in node]
    if len(values) == 1:
        yield from build_lines('──', '  ', values[0])
        return

    start, *mid, end = values
    yield from build_lines('┬─', '│ ', start)
    for value in mid:
        yield from build_lines('├─', '│ ', value)
    yield from build_lines('└─', '  ', end)

def build_lines(first, other, values):
    yield first + next(values)
    for value in values:
        yield other + value

结合一些执行示例:

>>> print(show_tree(('01', ('02',  '03', '04'), '05', (('06', '07'), '08'), ('09', ('10', '11'), ('12', '13'), '14'), '15')))
┬─01
├─┬─02
│ ├─03
│ └─04
├─05
├─┬─┬─06
│ │ └─07
│ └─08
├─┬─09
│ ├─┬─10
│ │ └─11
│ ├─┬─12
│ │ └─13
│ └─14
└─15
>>> print(show_tree(('A', 'B multi-word item', ('C', 'D'), ('E', '', 'F'), 'G')))
┬─A
├─B multi-word item
├─┬─C
│ └─D
├─┬─E
│ ├─
│ └─F
└─G
>>> print(show_tree((1, ((2,),), (3, 4, (5,)))))
┬─1
├─────2
└─┬─3
  ├─4
  └───5

相关问题 更多 >