如何不使用递归生成<ul><li>树,使用Python或其他语言?

4 投票
2 回答
1036 浏览
提问于 2025-04-15 22:41
class tree:
    def __init__(self, name='a', childs=[]):
        self.name = name
        self.childs = childs

输出:

<ul>
    <li>
    Introduction
    <ul>
        <li>Sub Intro</li>
    </ul>
    </li>

    <li>Module 1</li>
</ul>

2 个回答

-1

也许可以像这样:

NEW=object()
END=object()

class tree:
    def __init__(self, name='a', childs=[]):
        self.name = name
        self.childs = childs

    def __str__(self):
        indent=0
        result=[]
        for i in self.childs:
            if i is NEW:
                result.append('%s<ul>\n'%('    '*indent))
                indent+=1
            elif i is END:                
                indent-=1
                result.append('%s</ul>\n'%('    '*indent))
            else:
                result.append('%s<li>%s</li>\n'%('    '*indent, i))
        return ''.join(result)



print tree('test', [NEW, 'Introduction', NEW, 'Sub Intro', END, 'Module 1', END])
2

要生成嵌套列表而不使用递归,你只需要记录当前的嵌套层级。当你进入更深的嵌套时,就把层级加一;当你回到上层时,就把层级减一。

处理像关闭标签这样的事情,最简单的方法是用一个栈(在Python中可以用列表来实现)。当你把打开标签放入输出时,就把对应的关闭标签放到栈里。当你退出某个嵌套层级时,就把这些关闭标签从栈里取出来。

你没有提到输入的格式……所以我们假设它看起来像这样:

= Introduction
== Sub Intro
= Module 1

然后类似这样的内容:

 def pref_txt_to_ul(txt):
    nesting = 0
    closing_tags = list()
    for x in txt:
        if len(x.split()) < 2:
            continue
        prefix, content = x.split(None,1)
        nd = len(prefix)           ## new depth
        assert prefix == "=" * nd  ## First "word" is all = characters

        if nd > nesting:
            print "\n", " " * nesting * 4, "<ul>" * (nd - nesting), ## Push new opening tags into output
            closing_tags.append('</ul>' * (nd - nesting))  ## push closing tags for later
        elif nd < nesting:
            for x in range(nesting - nd):
                if closing_tags:
                    print " " * nesting * 4, closing_tags.pop(),  ## Pop closing tags
        nesting = nd
        print "\n", " " * nesting * 4, "<li>%s</li>" % content,  # push out this item (at new depth)
    ## After all text is done:
    while closing_tags:
        print closing_tags.pop(),   # Pop off remaining cloing tags

……应该可以解决问题(虽然方法比较粗糙)。

需要注意的是,我并没有强制规定嵌套层级只能增加1。比如,如果输入从=一下子变成======,就会生成多余的标签,并把这些多余的标签放入关闭标签的栈里。

注意:我只是回答了关于如何处理嵌套而不使用递归的具体问题。从你的例子(使用HTML无序列表标签)来看,你的真正目标可能是生成有效的HTML。在这种情况下,有很多Python工具比我在这个例子中使用的粗糙文本处理要好得多。你可以在Yahoo或Google上搜索:Python "generate HTML",会找到成千上万的页面,介绍如何做到这一点以及有哪些可用的工具。

(我记得多年前我用过HTMLgen,现在它仍然可以作为Debian包使用,但似乎在PyPI(Python包索引)上已经不再更新了……肯定有更新更频繁的包。大多数人似乎使用像Genshi或Mako这样的模板引擎。)

撰写回答