【问题标题】:Efficient algorithm / recursive function to nest items from a list从列表中嵌套项目的高效算法/递归函数
【发布时间】:2015-12-29 20:37:29
【问题描述】:

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

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

  • 按主题/slug 获取所有 cmets
  • 获取用户的所有 cmets

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

嘿,很酷的帖子#顶级 lvl 评论

谢谢! #回复评论

Foo 酒吧! #回复回复

等等……

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

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

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

到目前为止很容易,对吧?我现在遇到的问题是在帖子下方显示 cmets。当只有顶级 cmets 时,这很容易。只需获取一个特定 slug 的所有 cmets,按日期/评级/...对它们进行排序,然后使用我的 HTML 视图引擎编译它们。

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

原始列表(简化)

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

预期输出

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

我尝试使用一个非常奇怪的递归函数来创建我的预期输出。除非它效率不高。因此,由于我真的很沮丧并且觉得没有解决这个问题有点愚蠢,所以我决定寻求您的帮助。

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

【问题讨论】:

  • 我们不能有另一个名为level 的字段来指示深度吗?在您的示例中,level = 0 表示父级,level = 1 表示 id = 2 的评论等等?如果有多个 cmet 在同一 level 可以安排每个日期/时间戳?
  • @SKY 这是可能的。我只是不确定它会如何解决我的问题:|
  • 我会想象以下方式:Hey, cool post # top lvl comment 将是父母,因此level = 0Thanks! # reply to comment 将是回复,level = 1Foo Bar! # reply to reply 将有 level = 2。我会对所有父 cmets 重复相同的操作(每个父评论都有 level = 0),并且会有自己的回复线程
  • @SKY 你能用一个真实的例子来发布这个作为答案吗?我仍然无法通过您的逻辑获得预期的输出。或者至少是一种如何用它创建我的 HTML 的方法。
  • @Brettetete - 你会遇到 foo 是 bar 的父级而 bar 也是 foo 的父级的情况吗?如果我们不小心,这可能会造成无限循环。

标签: javascript node.js algorithm nested


【解决方案1】:

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

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);

【讨论】:

  • 你让我很开心..即使我可以面对手掌,你的解决方案实际上非常简单明了。
猜你喜欢
  • 1970-01-01
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 2016-05-28
  • 2015-04-17
  • 2014-08-07
  • 1970-01-01
相关资源
最近更新 更多