4

I have a structure like this

[
    {"id": "as2is0", "replies": [{"id": "e345k2e", "replies": [. . .]} ]},
    {"id": "2ishkl8"}
] . . .

where it is hard to predict how many replies a comment has. I basically want to loop through every single comment, be it a reply or top-level comment. How do I do this? There can be replies to other replies as well, so my basic loop solution doesn't work.

5
  • I assume you already have recursive solution... Converting to "basic loop" covered in stackoverflow.com/questions/159590/… Commented Dec 9, 2018 at 7:47
  • I think this is not valid array syntax to start with... It looks more like an object to me. An array should contain items, not key& value pairs. Commented Dec 9, 2018 at 7:49
  • As @RubyRacer mentioned, the syntax is not correct. Please post a sample of actual data with valid format. Commented Dec 9, 2018 at 7:50
  • @Jeto sorry, I have now posted what it looks like. Commented Dec 9, 2018 at 7:54
  • I have posted my answer below taking into consideration that the level of the comment and replies matter. Maybe you want to do something different for deep comments/replies Commented Dec 9, 2018 at 8:32

4 Answers 4

3

What you want is a recursive function, which means it calls itself under certain conditions. Here's an example

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

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a very simple recursive function to just print the ids to get you started:

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

The idea is to traverse the tree via calling getComments on every level and keep doing so until there is no longer any children/replies.

Comments

0

If you're interested in retrieving flattened comments first, as opposed to doing your stuff directly while looping over it (what other answers point you to), you can do the following:

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

This will also ensure any property that isn't replies (not just id, potentially others too if you have them) will remain in the flattened collection.

Comments

0

You will need to use recursion to resolve your problem. I am not sure what you want to do with each reply, or what action is needed on each sub-comment, but in my snippet below, I assumed that you want to parse them in a tree-like structure, with indentations to mark their level in the tree.

Of course, you can change the parsing code and replace it with whatever action is needed in your case.

// 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;
   }
   
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.