4

The Below code, not returning a flat array, is highly confusing, Need a flat array of deeply nested array of objects

have attached jsfiddle link https://jsfiddle.net/k6swuvox/

const arr = [{
  id: 1,
  name: 'XYZ 1'
}, {
  id: 2,
  name: 'XYZ 2',
  children: [{
    id: 5,
    name: 'XYZ 5'
  }, {
    id: 6,
    name: 'XYZ 6',
    age: 29,
    children: [{
      id: 7,
      name: 'XYZ 7'
    }, {
      id: 8,
      name: 'XYZ 8'
    }]
  }]
}, {
  id: 3,
  name: 'XYZ 3'
}, {
  id: 4,
  name: 'XYZ 4'
}]


const flats = data => data.map(e => {
  if (e.children) {
    return [...flats(e.children), e]
  } else {
    console.log("E", e);
    return e
  }
})

console.log(flats(arr));

1
  • Just calling flats(arr).flat() is sufficient in your code. Commented Apr 10, 2021 at 21:51

3 Answers 3

1

With your current code, you will sometimes return an array from the callback:

return [...flats(e.children),e]

and you'll sometimes return a plain object:

else {console.log("E",e);return e }

so the result will be a mix of arrays and plain objects, instead of an array of only objects.

Use flatMap instead, which will implement the flattening you're looking for for you. You'll also need to remove the .children property from items with children before returning them.

const arr=[{id:1,name:"XYZ 1"},{id:2,name:"XYZ 2",children:[{id:5,name:"XYZ 5"},{id:6,name:"XYZ 6",age:29,children:[{id:7,name:"XYZ 7"},{id:8,name:"XYZ 8"}]}]},{id:3,name:"XYZ 3"},{id:4,name:"XYZ 4"}];

const flats = data => data.flatMap(e=>{
  const { children, ...objWithoutChildren } = e;
  return children
    ? [...flats(children), objWithoutChildren]
    : e;
});

console.log(flats(arr));

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

1 Comment

When an answer solves your problem, you may consider upvoting and/or marking it as Accepted (check the checkbox on the left) to indicate that the issue is resolved :)
1

Here is an iterative solution using object-scan

// const objectScan = require('object-scan');

const arr = [{ id: 1, name: 'XYZ 1' }, { id: 2, name: 'XYZ 2', children: [{ id: 5, name: 'XYZ 5' }, { id: 6, name: 'XYZ 6', age: 29, children: [{ id: 7, name: 'XYZ 7' }, { id: 8, name: 'XYZ 8' }] }] }, { id: 3, name: 'XYZ 3' }, { id: 4, name: 'XYZ 4' }];

const flatten = objectScan(['**(^children$).id'], {
  useArraySelector: false,
  rtn: 'parent',
  reverse: false,
  afterFn: (state) => {
    state.result = state.result.map(({ id, name }) => ({ id, name }));
  }
});

console.log(flatten(arr));
// => [ { id: 1, name: 'XYZ 1' }, { id: 2, name: 'XYZ 2' }, { id: 5, name: 'XYZ 5' }, { id: 6, name: 'XYZ 6' }, { id: 7, name: 'XYZ 7' }, { id: 8, name: 'XYZ 8' }, { id: 3, name: 'XYZ 3' }, { id: 4, name: 'XYZ 4' } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Comments

0

Need a flat array of deeply nested array of objects

In that case, I'd prefer recursive to get the flexible and high deep level array.

const arr = [{id:1,name:'XYZ 1'},{id:2,name:'XYZ 2',children:[{id:5,name:'XYZ 5'},{id:6,name:'XYZ 6',age:29,children:[{id:7,name:'XYZ 7'},{id:8,name:'XYZ 8'}]}]},{id:3,name:'XYZ 3'},{id:4,name:'XYZ 4'}];

const recursive = (array) => array.reduce((acc, {children = [], ...others}) => {
  acc.push(others);
  if(children.length > 0) // Base recurisve here.
    acc = acc.concat(recursive(children));
  return acc;
}, []);

console.log(recursive(arr));

==> As a result, the content structure will make sure like this enter image description here

1 Comment

Yes. You can accept my answer by clicking the tick to help the reader in the future @yaayhai meta.stackexchange.com/questions/5234/…

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.