what is wrong in the array map iteration

Viewed 78

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

3 Answers

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

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/object-scan@15.0.0"></script>

Disclaimer: I'm the author of object-scan

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

Related