递归查找深度嵌套的对象数组

Recursively find a deeply nested array of objects

提问人:desh 提问时间:2/2/2023 最后编辑:desh 更新时间:2/2/2023 访问量:91

问:

比方说,如果我们有一个深度嵌套的评论评论。

const comments = [
  {
    id: 1,
    text: "Comment 1",
    comments: [
      {
        id: 11,
        text: "Comment 1a",
        comments: [
          {
            id: 111,
            text: "Comment 11a",
            comments: [],
          },
          {
            id: 112,
            text: "Comment 11b",
            comments: [],
          },
          {
            id: 113,
            text: "Comment 11c",
            comments: [],
          },
        ],
      },
      {
        id: 12,
        text: "Comment 12",
        comments: [
          {
            id: 121,
            text: "Comment 12a",
            comments: [],
          },
          {
            id: 122,
            text: "Comment 12b",
            comments: [],
          },
          {
            id: 123,
            text: "Comment 12c",
            comments: [],
          },
        ],
      },
      {
        id: 13,
        text: "Comment 1c",
        comments: [
          {
            id: 124,
            text: "Comment 13a",
            comments: [],
          },
          {
            id: 125,
            text: "Comment 13b",
            comments: [],
          },
          {
            id: 126,
            text: "Comment 13c",
            comments: [],
          },
        ],
      },
    ],
  },
  {
    id: 2,
    text: "Comment 2",
    comments: [
      {
        id: 21,
        text: "Comment 2a",
        comments: [
          {
            id: 127,
            text: "Comment 21a",
            comments: [],
          },
          {
            id: 128,
            text: "Comment 21b",
            comments: [],
          },
          {
            id: 129,
            text: "Comment 21c",
            comments: [
              {
                id: 130,
                text: "Comment 21cc",
                comments: [
                  {
                    id: 131,
                    text: "Comment 21ccc",
                    comments: [],
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 22,
        text: "Comment 2b",
        comments: [
          {
            id: 135,
            text: "Comment 21a",
            comments: [],
          },
          {
            id: 132,
            text: "Comment 21b",
            comments: [],
          },
          {
            id: 133,
            text: "Comment 21c",
            comments: [],
          },
        ],
      },
      {
        id: 23,
        text: "Comment 2c",
        comments: [],
      },
    ],
  },
  {
    id: 3,
    text: "Comment 3",
    comments: [
      {
        id: 31,
        text: "Comment 3a",
        comments: [],
      },
      {
        id: 32,
        text: "Comment 3b",
        comments: [],
      },
      {
        id: 33,
        text: "Comment 3c",
        comments: [],
      },
    ],
  },
];

我们如何找到深度嵌套的注释,例如 id 为 131 的注释? 我尝试了以下方法,它有效。

function recursiveFind(comments, commentId) {
  const result = [];
  function loop(comments, commentId, result) {
    for (const comment of comments) {
      if (comment.id === commentId) {
        result.push(comment);
      }
      if (result.length <= 0 && comment.comments) {
        loop(comment.comments, commentId, result);
      }
    }
  }
  loop(comments, commentId, result);
  return result.length > 0 ? result[0] : false;
}
const found = recursiveFind(comments, 131);
console.log(found);//returns object

有没有更优雅的方法可以做到这一点?我知道另一种选择是展平数组然后返回对象?

但是,有没有更好的方法可以做到这一点?

谢谢。

编辑:是的,ID是唯一的,我已经更正了ID。

JavaScript 递归 嵌套列表

评论

1赞 Roko C. Buljan 2/2/2023
鉴于该用户 (?),返回注释数组会更有意义ID,而不是对象。或者,如果它不是用户 ID,则您的问题格式不正确。(注意:ID重复)130
0赞 desh 2/2/2023
@RokoC.Buljan 对不起,我的坏,id 应该是唯一的

答:

3赞 gog 2/2/2023 #1

我们已经在 JS 中有一个免费的树行者 - :JSON.stringify

function find(data, fn) {
    let found = []

    JSON.stringify(data, (key, val) => {
        if (fn(val))
            found.push(val)
        return val
    })

    return found
}

然后简单地说:

results = find(comments, x => x.id === 131)

评论

1赞 Roko C. Buljan 2/2/2023
真正优雅的解决方案
1赞 Peter Thoeny 2/2/2023 #2

您可以使用 a 和 recursion:.reduce()

const comments = [ { id: 1, text: "Comment 1", comments: [ { id: 11, text: "Comment 1a", comments: [ { id: 111, text: "Comment 11a", comments: [], }, { id: 112, text: "Comment 11b", comments: [], }, { id: 113, text: "Comment 11c", comments: [], }, ], }, { id: 12, text: "Comment 12", comments: [ { id: 121, text: "Comment 12a", comments: [], }, { id: 122, text: "Comment 12b", comments: [], }, { id: 123, text: "Comment 12c", comments: [], }, ], }, { id: 13, text: "Comment 1c", comments: [ { id: 124, text: "Comment 13a", comments: [], }, { id: 125, text: "Comment 13b", comments: [], }, { id: 126, text: "Comment 13c", comments: [], }, ], }, ], }, { id: 2, text: "Comment 2", comments: [ { id: 21, text: "Comment 2a", comments: [ { id: 127, text: "Comment 21a", comments: [], }, { id: 128, text: "Comment 21b", comments: [], }, { id: 129, text: "Comment 21c", comments: [ { id: 130, text: "Comment 21cc", comments: [ { id: 131, text: "Comment 21ccc", comments: [], }, ], }, ], }, ], }, { id: 22, text: "Comment 2b", comments: [ { id: 130, text: "Comment 21a", comments: [], }, { id: 132, text: "Comment 21b", comments: [], }, { id: 133, text: "Comment 21c", comments: [], }, ], }, { id: 23, text: "Comment 2c", comments: [], }, ], }, { id: 3, text: "Comment 3", comments: [ { id: 31, text: "Comment 3a", comments: [], }, { id: 32, text: "Comment 3b", comments: [], }, { id: 33, text: "Comment 3c", comments: [], }, ], }, ];

function recursiveFind(comments, commentId) {
  const result = comments.reduce((acc, obj) => {
    if(obj.id === commentId) {
      acc = obj;
    } else if(obj.comments.length) {
      const found = recursiveFind(obj.comments, commentId);
      if(found) acc = found;
    }
    return acc;
  }, null);
  return result;
}

console.log('search id 131:', recursiveFind(comments, 131));

输出:

{
  "id": 131,
  "text": "Comment 21ccc",
  "comments": []
}

文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

更新 1,以解决 ID 不唯一的反馈。我还删除了嵌套注释;如果需要,请删除.map(obj => ({ id: obj.id, text: obj.text }))

UPDATE 2 还原了 Update 1,因为 ID 实际上是唯一的。

评论

1赞 Roko C. Buljan 2/2/2023
这将只返回一条注释,而按用户 ID 返回一组注释会更有意义。 (请注意,ID 指的是用户,因为存在重复的 ID。 - 或者也许是 OP 方面的失误。130
0赞 Peter Thoeny 2/2/2023
@RokoC.Buljan:请参阅更新的答案,以解决 ID 不唯一的反馈。
1赞 desh 2/2/2023
谢谢。是的,id应该是唯一的,我不小心添加了重复的id是我的错。
2赞 Peter Thoeny 2/2/2023
好的,我恢复了更新1