JS - 如何循环遍历对象数组中的嵌套数组

4
我有这样的一个结构
[
    {"id": "as2is0", "replies": [{"id": "e345k2e", "replies": [. . .]} ]},
    {"id": "2ishkl8"}
] . . .

有时很难预测一个评论会有多少回复。我想要遍历每一条评论,无论是回复还是顶级评论。我该怎么做呢?还可能有对其他回复的回复,所以我的基本循环解决方案行不通。


我假设你已经有了递归解决方案... 转换为“基本循环”的方法在 https://dev59.com/ZHVC5IYBdhLWcg3w21Mq 中有介绍。 - Alexei Levenkov
我认为这不是有效的数组语法... 对我来说更像一个对象。数组应该包含项目,而不是键值对。 - Ruby Racer
正如@RubyRacer所提到的,语法不正确。请发布一个具有有效格式的实际数据示例。 - Jeto
@Jeto 抱歉,我现在已经发布了它的外观。 - ICanKindOfCode
我已经发布了我的答案,考虑到评论和回复的水平很重要。也许你想为深度评论/回复做一些不同的事情。 - Ahmad
4个回答

3
您需要的是一个递归函数,也就是在特定条件下会调用自身的函数。这里有一个例子。

const data = [
    {
      id: "abc",
      replies: [
        {id: "def", replies: [
          {id: 'ghi', replies: [] }
        ]} 
      ]
    },
    {
      id: "jkl",
      replies: [
        {id: "mno", replies: [
          {id: 'pqr', replies: [] }
        ]} 
      ]
    }
]

function logReplies(data) {
  data.forEach(item => {
    console.log('id:', item.id);
    if (item.replies) {
      logReplies(item.replies);
    }
  });
}

logReplies(data);

Documentation

https://developer.mozilla.org/en-US/docs/Glossary/Recursion


1

这里有一个非常简单的递归函数,只是打印ids,让你开始:

const data = [{
    id: "as2is0",
    replies: [{
      id: "e345k2e",
      replies: [{
        id: "e34112e",
        replies: []
      }]
    }]
  },
  {
    "id": "2ishkl8"
  }
]

// notice the function accepts an array as a parameter
const getComments = arr => arr.forEach(x => {   // <-- for every element
  if(x.id)
    console.log(x.id)
  if(x.replies)    // <-- if there are any children
    getComments(x.replies)  // <-- call with the children array as parameter now
})

getComments(data)  // <-- do the initial call of the function

这个想法是通过在每一层级上调用getComments来遍历树,直到没有任何子元素/回复为止。


0
如果你对先检索扁平化的评论感兴趣,而不是在循环过程中直接处理(其他答案指向的方式),你可以执行以下操作:

const comments = [
  {"id": "as2is0", "replies": [{"id": "e345k2e", "replies": []} ]},
  {"id": "2ishkl8"}
];
  
function getFlattenedComments(comments) {
  const flattenedComments = [];
  for ({replies, ...commentWithoutReplies} of comments) {
    flattenedComments.push(commentWithoutReplies);
    if (replies) {
      flattenedComments.push(...getFlattenedComments(replies));
    }
  }
  return flattenedComments;
}

console.log(getFlattenedComments(comments));

这也将确保任何不是replies的属性(不仅仅是id,如果您有其他属性的话)都将保留在扁平化的集合中。


0

你需要使用递归来解决你的问题。我不确定你想对每个回复做什么,或者每个子评论需要什么操作,但在下面的代码片段中,我假设你想以树形结构解析它们,并使用缩进标记它们在树中的级别。

当然,你可以更改解析代码,并用你需要的任何操作替换它。

// here is my attempt at building a complex layers of nested comments
var comments = [
    {"id": "as2is0", "replies": [
                     {"id": "e345k2e", "replies": []},
                     {"id": "f12ba55", "replies": [{"id":"st123abc","replies":[{"id": "y345k2e", "replies": []}]}]} ]},
    {"id": "k345k2e", "replies": [{"id": "q96yyt", "replies": []}]},
    {"id": "2ishkl8"}
];

// begin at the outer level, parse each element separately
comments.forEach(function(c){
  console.log(parse(c));
});


// the parse function takes two parameters: the comment object and the level
function parse(c,lvl) {
   //if level is not specified, it is assumed to be root level
   if(!lvl) { lvl = 0 }
   
   // if current comment contains no replies, or empty array:
   if(!c.replies || c.replies.length==0) {
      return  c.id;   
   } else {
      // build a string to contain all nested replies
      var str = c.id + " : " ;
      // iterate through all replies of current comment
      c.replies.forEach(function(r){
        
        str +=  "\n" ;                // add a new line
        str += ("  ").repeat( lvl+1); // indent reply as depending on the level
        str += parse(r,(lvl+1));      // recursive call to parse cunction
                                      // but with one level deeper
      });
      return str;
   }
   
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接