展平 javascript 对象数组

Posted

技术标签:

【中文标题】展平 javascript 对象数组【英文标题】:flatten javascript array of objects 【发布时间】:2018-02-24 20:51:28 【问题描述】:

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

[
    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 实现它的最佳方法是什么。

【问题讨论】:

【参考方案1】:

不需要下划线/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】:

我会使用.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));

【讨论】:

【参考方案3】:

您可以尝试调整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>

这有帮助吗?

【讨论】:

【参考方案4】:

递归函数适用于任何深度的迭代。

带有一些 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>

【讨论】:

【参考方案5】:

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

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; 

【讨论】:

以上是关于展平 javascript 对象数组的主要内容,如果未能解决你的问题,请参考以下文章

在javascript中展平数组[重复]

具有嵌套对象的多个对象的展平数组

展平数组内的对象

展平对象中的数组

将包含对象的数组展平为 1 个对象

雪花中具有多个 JSON 对象的横向展平数组