用于嵌套列表中项目的高效算法/递归函数

时间:2015-12-29 20:37:30

标签: javascript node.js algorithm nested

我目前正在实施自己的评论系统。不幸的是,Disqus或任何其他评论平台都不符合我的要求。

我使用NodeJS和MongoDB作为后端。我需要在我的数据库上运行基本上两个查询:

  • 获取主题/ slug的所有评论
  • 获取用户的所有评论

可以对主题发表评论或回复评论。

  

嘿,很酷的帖子#top lvl comment

     
    

谢谢! #回复评论

         
      

Foo Bar! #回复回复

             
        

依旧......

      
    
  

所以我的数据库架构看起来像

{
    id: ObjectId,
    text: string,
    author: { id: ObjectId, name: string },
    parent: nullable ObjectId,
    slug: string/number/whatever
}

如果parent为空,则为顶级评论,否则为回复。

到目前为止相当容易,对吗?我现在遇到的问题是在帖子下面显示评论。如果只有顶级评论,那将很容易。只需获取一个特定slug的所有注释,按日期/评级/ ...对它们进行排序,然后使用我的HTML View Engine进行编译。

但实际上有回复,我只是停留在需要组织结构的地方。我想将回复嵌入我的列表中的评论

原始列表(简化)

[
  { id: 1, text: 'foo', parent: null },
  { id: 2, text: 'bar', parent: 1 },
  // ...
]

预期产出

[
  { id: 1, text: 'foo', replies: [
    { id: 2, text: 'bar' },
  ] },
]

我尝试使用递归函数创建我的预期输出,这非常奇怪。除非它不会非常有效。所以,因为我真的感到沮丧,有点愚蠢没有解决这个问题,所以我决定请求你的帮助。

我想解决的实际问题:如何渲染我的评论,他们是否正确嵌套等。
我要问的问题是:如何以有效的方式组织我的扁平结构来解决上述问题?

1 个答案:

答案 0 :(得分:2)

这是一种具有线性复杂性的方法:

var comments = [{
  id: 3,
  text: 'second',
  parent: 1
}, {
  id: 1,
  text: 'root',
  parent: null
}, {
  id: 2,
  text: 'first',
  parent: 1
}, {
  id: 5,
  text: 'another first',
  parent: 4
}, {
  id: 4,
  text: 'another root',
  parent: null
}];

var nodes = {};

//insert artificial root node
nodes[-1] = {
  text: 'Fake root',
  replies: []
};

//index nodes by their id
comments.forEach(function(item) {
  if (item.parent == null) {
    item.parent = -1;
  }
  nodes[item.id] = item;
  item.replies = [];
});

//put items into parent replies
comments.forEach(function(item) {
  var parent = nodes[item.parent];
  parent.replies.push(item);
});

//root node replies are top level comments
console.log(nodes[-1].replies);