展平 javascript 个对象数组

flatten javascript array of objects

我有一个具有层次结构的对象数组,如下所示:

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

我要压扁它:

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

我已经尝试了 _.flatten()_.flatMap(),但它没有产生我需要的东西。最好使用 lodash.jsunderscore.js.

实现它的最佳方法是什么

不需要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));

我会使用 .reduce 和递归来做到这一点。这是我使用 Array.reduce 的实现,但您可以使用下划线的 reduce 函数做很多相同的事情。

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

您可以尝试调整 this answer 中给出的 flatten 函数,并稍微扭曲对象结构的逻辑。

//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>

这有什么帮助吗?

递归函数是实现任何深度迭代的方法。

使用一些 ES2015 和 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>

您可以使用一些破坏并使用递归函数来收集所有想要的物品。

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

在 EDGE 上,您需要使用不同的默认值。

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