2017-01-05 4 views
0

私はホビープロジェクトの一部としてコメントシステムを作成しようとしていますが、データベースからフェッチされたコメントオブジェクトを再帰的に並べ替える方法はわかりません。私は、ツリー内のこれらのオブジェクトをソートする必要があるデータベースからデータを持ってたらpymysqlコメントオブジェクトをツリーに再帰的に変換する

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) 

:私は、次のデータモデルを持っているリレーショナルデータベースを使用しています。例の入力は、例えば次のようになります。

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> 
      ] 

、期待される結果は次のようになります。

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>, ...]} ... 

任意のコメントオブジェクトは子供の無限の量を持つことができます。 Redditや他の同様のソーシャルメディアサイトで使用されているコメントシステムに似ています。私はフラスコや神社を使用していますし、おそらく私がマニュアルに記載されていこのような何かを行うことができ、レンダリングのために :私はこれを行う前にデータを並べ替える方法

<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 %} 

は私はありません何です考え出す

答えて

1

非常に単純なアプローチはこれです:

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 

だから、最初の空のようchildrenでルート要素を記入した後、第2のパスで、あなたが子供を埋めます。これは、さらに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 

ここに解決策は、あなたが私たちを示してきた予想出力と一致します。


あなたは本物の木を持っていると思いますが、この

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 
+0

を試してみてくださいしかし、これはコメントの無限に深い木のためにできるようになりますか? – Marius

+1

@マリアス任意の深い樹木を2回通過させることができます。私は答えを更新しました。これは、前と同じように単一パスで実装することができます。私は運動としてあなたにそれを残します。 – freakish

関連する問題