简体   繁体   English

将pymysql注释对象递归转换为树

[英]Converting pymysql Comment objects to tree recursively

I am trying to create a comment system as a part of a hobby project, but I cant figure out how to recursively sort the Comment object once they have been fetched from the database. 我正在尝试创建一个注释系统,作为一个业余项目的一部分,但是当从数据库中获取注释对象时,我无法弄清楚如何对注释对象进行递归排序。 I'm using a relational database which has the following datamodel: 我正在使用具有以下数据模型的关系数据库:

class Comment(Base):
    __tablename__ = 'comments'
    id = Column(Integer, primary_key=True)
    comment = Column(String(), nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
    post_id = Column(Integer, ForeignKey('posts.id'), nullable=False)
    parent_id = Column(Integer, ForeignKey('comments.id'), nullable=False)

Once I've got the data from the database I need to sort these objects in a tree. 从数据库中获取数据后,我需要对这些对象进行树状排序。 Example input could for example be: 输入示例例如可以是:

comments = [
            <models.Comment object at 0x104d80358>,
            <models.Comment object at 0x104d803c8>,
            <models.Comment object at 0x104d80470>, 
            <models.Comment object at 0x104d80518>,
            <models.Comment object at 0x104d805c0>,
            <models.Comment object at 0x104d80668>
           ]

And expected result could be: 预期结果可能是:

comment_dict = {1: {'comment':<Comment.object>, 'children':[]},
               {2: {'comment':<Comment.object>, 'children':[<Comment.object>, ...]},
               {3: {'comment':<Comment.object>, 'children':[]},
               {4: {'comment':<Comment.object>, 'children':[<Comment.object>, ...]} ...

Any comment object can have an infinite amount of children. 任何评论对象可以具有无限数量的子代。 Almost like the comment system used on reddit and other similar social media sites. 就像在reddit和其他类似社交媒体网站上使用的评论系统一样。 For the rendering I'm using flask and Jinja and could possibly do something like this which I found in the documentation: 对于渲染,我使用了flask和Jinja,并且可能会做类似在文档中找到的操作:

<ul class="sitemap">
{%- for item in sitemap recursive %}
    <li><a href="{{ item.href|e }}">{{ item.title }}</a>
    {%- if item.children -%}
        <ul class="submenu">{{ loop(item.children) }}</ul>
    {%- endif %}</li>
{%- endfor %}

How I sort the data before doing this is what I'm not figuring out. 我没有弄清楚在执行此操作之前如何对数据进行排序。

The very simple approach is this: 非常简单的方法是这样的:

def comments_to_dict(comments):
    result = {}
    for comment in comments:
        result[comment.id] = {
            'comment': comment,
            'children': []
        }
    for comment in comments:
        result[comment.parent_id]['children'].append(comment)
    return result

So first you fill root elements with children as empty and then in second pass you fill children. 因此,首先用children将根元素填充为空,然后在第二遍中将儿童填充。 This can be further improved by doing only one pass over comments : 仅需对comments进行一次传递,即可进一步改善此效果:

def comments_to_dict(comments):
    result = {}
    for comment in comments:
        if comment.id in result:
            result[comment.id]['comment'] = comment
        else:
            result[comment.id] = {
                'comment': comment,
                'children': []
            }

        if comment.parent_id in result:
            result[comment.parent_id]['children'].append(comment)
        else:
            result[comment.parent_id] = {
                'children': [comment]
            }
    return result

The solution here matches the expected output you've shown us. 这里的解决方案与您向我们展示的预期输出匹配。


If however you want to have a real tree, then try this 但是,如果您想有一棵真正的树,请尝试此操作

def comments_to_dict(comments):
    index = {}
    for comment in comments:
        index[comment.id] = {
            'comment': comment,
            'children': []
        }
    for obj in index.itervalues():
        pid = obj['comment'].parent_id
        index[pid]['children'].append(obj)
    return index

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM