1

I am trying to nest elements within each-other, but today I am having a brain fart.

If an element in the array is isParent: true, then it will create a new array within the exist array, and all following elements will be nested inside that array.

Here is what I have tried so far:

//input [{},{},{},{isParent}, {}, {}, {isParent}, {}, {}]
//desired output [{}, {}, {}, [{}, {}, {}, [{}, {}, {}]]]

var nestInParent = elements => {
      let ignoreIndexAfter = null;
      return elements.reduce((acc, { component, isParent }, index) => {
        if (isParent) {
          let remaining = elements.slice(index + 1);
   			ignoreIndexAfter = index;
          if (remaining.length > 0) {
            return [...acc, [component, ...nestInParent(remaining)]];
          } else {
            return [...acc, [component]];
          }
        } else {
			if(ignoreIndexAfter === null || index < ignoreIndexAfter){
               return [...acc, component];
            }
return acc;
        }
      }, []);
    };
const isParent = true;
const input = [
  {component:0},
  {component:1},
  {component:2},
  {isParent, component:3},
  {component:4},
  {component:5},
  {isParent, component:6},
  {component:7},
  {component:8}
];
const expected = [
  0,
  1,
  2,
  [
    3,
    4,
    5,
    [
      6,
      7,
      8
    ]
  ]
];
const output = nestInParent(input);
console.log("input:", input);
console.log("output:", output);
console.log("passes?", JSON.stringify(output) === JSON.stringify(expected));
.as-console-wrapper { max-height: 100% !important; }

3
  • what is if(t > startLen) return acc; supposed to do? Commented May 2, 2019 at 10:25
  • I edited the code, that's no longer in there. it works a bit better, but not quite. Commented May 2, 2019 at 10:28
  • The main problem is that you traverse the whole array with every recursive step. That is a waste of time, and makes things overly complicated. Don't use reduce if not appropriate. Commented May 2, 2019 at 10:32

2 Answers 2

2

You could also do this using reduce method and one variable to track if element with isParent prop is found.

const isParent = true;
const input = [{component:0},{component:1},{component:2},{isParent, component:3},{component:4},{component:5},{isParent, component:6},{component:7},{component:8}];

function nest(data) {
  let nested = false;
  return data.reduce((r, e, i) => {
    if(!nested) {
    	if(e.isParent) {
      	const res = nest(data.slice(i + 1))
        r.push([e.component, ...res])
        nested = true;
      } else {
        r.push(e.component)
      }
    }
    return r;
  }, [])
}

const result = nest(input);
console.log(result)

You can also write it like this.

const isParent = true;
const input = [{ component: 0 }, { component: 1 }, { component: 2 }, { isParent, component: 3 }, { component: 4 }, { component: 5 },{ isParent, component: 6 }, { component: 7 }, { component: 8 }];

function nest(data, nested) {
  return data.reduce((r, e, i) => {
    if(!nested) {
      if(e.isParent && i != 0) {
        r.push(nest(data.slice(i)))
        nested = true;
      } else {
        r.push(e.component)
      }
    }
    return r;
  }, [])
}

const result = nest(input);
console.log(result)

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

Comments

2

I'd say that your code fails because it is overly complicated. You just need:

const result = [];
let current = result;

 for(const { component, isParent } of data) {
   if(isParent) {
     current.push(current = [component]);
   } else current.push(component);
 }

const input = [
  {component:0},
  {component:1},
  {component:2},
  {isParent: true, component:3},
  {component:4},
  {component:5},
  {isParent: true, component:6},
  {component:7},
  {component:8}
];

const result = [];
let current = result;

 for(const { component, isParent } of input) {
   if(isParent) {
     current.push(current = [component]);
   } else current.push(component);
 }

console.log(result);

Or if you really want to reduce, reduceRight:

const result = data.reduceRight((acc, { isParent, component }) => isParent ? [[component, ...acc]] : [component, ...acc], []);

const input = [
  {component:0},
  {component:1},
  {component:2},
  {isParent: true, component:3},
  {component:4},
  {component:5},
  {isParent: true, component:6},
  {component:7},
  {component:8}
];

const result = input.reduceRight((acc, { isParent, component }) =>
isParent ? [[component, ...acc]] : [component, ...acc], []);

console.log(result);

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.