简体   繁体   中英

reduce array of objects into nested arrays

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

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) 

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM