Aman Virk Aman Virk - 19 days ago 6
Javascript Question

Javascript: How to recursively group arrays based upon upcoming index value

I have a situation where I want to group the arrays into chunks based upon the value of the upcoming index. Let's consider this example

Input



var tokens = [{
tag: null,
line: 'starting of the file'
},
{
tag: 'each',
line: null
}, {
tag: null,
line: 'foo bar'
}, {
tag: null,
line: 'baz'
}, {
tag: 'endeach',
line: null
}, {
tag: null,
line: 'hello world'
}]


Expected Output



[{
tag: null,
line: 'starting of the file'
},
{
tag: 'each',
line: null,
childs: [{
tag: null,
line: 'foo bar'
}, {
tag: null,
line: 'baz'
}]
}, {
tag: null,
line: 'hello world'
}]


What really happening is all elements after the opening
each
tag are nested as childs. Now this can also happen recursively where there can be multiple
each
tags before the
endeach
.

Hope this makes sense!

Answer

Using Array.prototype.reduce(), whenever we encounter each we add the children array to the container array. Whenever we encounter endeach we remove the last array from container. We always items push to the last array in container. In the end the 1st array in container will include the tree:

function fold(arr) {
  return arr.reduce(function(container, item) {
    if (item.tag === 'endeach') {
      container.pop();
      return container;
    }
    
    container[container.length - 1].push(item);

    if (item.tag === 'each') {
      item.children = [];

      container.push(item.children);
    }
    
    return container;
  }, [[]])[0];
}

var tokens = [{
    tag: null,
    line: 'starting of the file'
  }, {
    tag: 'each',
    line: null
  }, {
    tag: null,
    line: 'foo bar'
  }, {
    tag: 'each',
    line: null
  }, {
    tag: null,
    line: 'foo bar21'
  }, {
    tag: null,
    line: 'baz21'
  }, {
    tag: 'endeach',
    line: null
  }, {
    tag: 'each',
    line: null
  }, {
    tag: null,
    line: 'foo bar22'
  }, {
    tag: null,
    line: 'baz22'
  }, {
    tag: 'endeach',
    line: null
  },{
    tag: null,
    line: 'baz'
  }, {
    tag: 'endeach',
    line: null
  }, {
    tag: null,
    line: 'hello world'
  }
];

var result = fold(tokens);

console.log(result);

Comments