flatten javascript array of objects

怎甘沉沦 提交于 2020-01-02 22:42:10

问题


I have an array of object with hierarchical structure, something like this:

[
    {name: 'ParentOne', children: [
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo', children: [
            {name: 'ParentOneChildTwoGrandChildOne'},
        ]},
    ]}, 
    {name: 'ParentTwo', children: [
        {name: 'ParentTwoChildOne', children: [
           {name: 'ParentTwoChildOneGrandChildOne'},
           {name: 'ParentTwoChildOneGrandChildTwo'}
        ]},
        {name: 'ParentTwoChildTwo'}
    ]}
];

I want to flatten it:

[
    {name: 'ParentOne'},
    {name: 'ParentOneChildOne'},
    {name: 'ParentOneChildTwo'},
    {name: 'ParentOneChildTwoGrandChildOne'},
    {name: 'ParentTwo'},
    {name: 'ParentTwoChildOne'},
    {name: 'ParentTwoChildOneGrandChildOne'},
    {name: 'ParentTwoChildOneGrandChildTwo'},
    {name: 'ParentTwoChildTwo'}
]

I have tried _.flatten() and _.flatMap(), but it does not produce what I need. What is the best way to achieve it preferably using lodash.js or underscore.js.


回答1:


No need for underscore/lodash.

const arr = [
    {name: 'ParentOne', children: [
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo', children: [
            {name: 'ParentOneChildTwoGrandChildOne'},
        ]},
    ]}, 
    {name: 'ParentTwo', children: [
        {name: 'ParentTwoChildOne', children: [
           {name: 'ParentTwoChildOneGrandChildOne'},
           {name: 'ParentTwoChildOneGrandChildTwo'}
        ]},
        {name: 'ParentTwoChildTwo'}
    ]}
];

function flatten(arr) {
    return arr? arr.reduce((result, item) => [
        ...result,
        { name: item.name },
        ...flatten(item.children)
    ], []) : [];
}

console.log(flatten(arr));



回答2:


Recursive functions is the way to go for any depth of iteration.

With some ES2015 and LoDash/Underscore

var arr = [{
  name: 'ParentOne',
  children: [{
    name: 'ParentOneChildOne'
  }, {
    name: 'ParentOneChildTwo',
    children: [{
      name: 'ParentOneChildTwoGrandChildOne'
    }, ]
  }, ]
}, {
  name: 'ParentTwo',
  children: [{
    name: 'ParentTwoChildOne',
    children: [{
      name: 'ParentTwoChildOneGrandChildOne'
    }, {
      name: 'ParentTwoChildOneGrandChildTwo'
    }]
  }, {
    name: 'ParentTwoChildTwo'
  }]
}];

var res = _.reduce(arr, (a, b) => {
  (rec = item => {
    _.each(item, (v, k) => (_.isObject(v) ? rec(v) : a.push(_.zipObject([k], [v]))))
  })(b);
  return a;
}, []);

console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>



回答3:


I would use .reduce and recursion to do this. Here's my implementation using Array.reduce, but you could do much the same with underscore's reduce function.

const arr = [
    {name: 'ParentOne', children: [
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo', children: [
            {name: 'ParentOneChildTwoGrandChildOne'},
        ]},
    ]}, 
    {name: 'ParentTwo', children: [
        {name: 'ParentTwoChildOne', children: [
           {name: 'ParentTwoChildOneGrandChildOne'},
           {name: 'ParentTwoChildOneGrandChildTwo'}
        ]},
        {name: 'ParentTwoChildTwo'}
    ]}
];

function flatten(arr) {
   return arr.reduce((result, current) => {
      if (current.children) {
         const children = flatten(current.children);
         delete current.children;
         result.push(current);
         result.push(...children);
      } else {
         result.push(current);
      }
      return result;
   }, [])
}

console.log(flatten(arr));



回答4:


You could try adapting the flatten function given in this answer, and slightly twist the logic to your object's structure.

//Your object
var data = [{
    name: 'ParentOne',
    children: [{
        name: 'ParentOneChildOne'
      },
      {
        name: 'ParentOneChildTwo',
        children: [{
          name: 'ParentOneChildTwoGrandChildOne'
        }, ]
      },
    ]
  },
  {
    name: 'ParentTwo',
    children: [{
        name: 'ParentTwoChildOne',
        children: [{
            name: 'ParentTwoChildOneGrandChildOne'
          },
          {
            name: 'ParentTwoChildOneGrandChildTwo'
          }
        ]
      },
      {
        name: 'ParentTwoChildTwo'
      }
    ]
  }
];

//georg's flatten function
flatten = function(x, result, prefix) {
  if (_.isObject(x)) {
    _.each(x, function(v, k) {
      flatten(v, result, prefix ? prefix + '_' + k : k)
    })
  } else {
    result[prefix] = x
  }
  return result
}

//using the function on your data
result = flatten(data, {});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Does this help at all?




回答5:


You could use some destruction and use a recursive function for collecting all wanted items.

var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
    flat = (r, { name, children = [] }) => [...r, { name }, ...children.reduce(flat, []) ],
    result = array.reduce(flat, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

On EDGE, you need a different use of default values.

var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
    flat = (r, { name, children }) => [...r, { name }, ...(children || []).reduce(flat, []) ],
    result = array.reduce(flat, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


来源:https://stackoverflow.com/questions/46243349/flatten-javascript-array-of-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!