如何将具有相同属性的对象合并到数组中? [英] How to merge objects with the same properties into an Array?

查看:116
本文介绍了如何将具有相同属性的对象合并到数组中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将2个具有相同属性的对象合并到一个数组中.

I would like to merge 2 objects with the same properties into an Array.

以这个为例:

object1 = {"id":1,
           "name":name1,
           "children":[{"id":2,"name":name2}]
          };
object2 = {"id":3,
           "name":name3,
           "children":[{"id":4,"name":name4}]
          };
object3 = {"id":1,
           "name":name1,
           "children":[{"id":6,"name":name6}]
          };
var result = Object.assign(result,object1,object2,object3);

预期结果:

JSON.stringify([result]) =[
                           {"id":1,
                            "name":name1,
                            "children":[{"id":2,"name":name2},
                                       {"id":6,"name":name6}]
                           },
                           {"id":3,
                            "name":name3,
                            "children":[{"id":4,"name":name4}]
                           }
                          ]

实际结果:

JSON.stringify([result]) = [
                            {"id":3,
                             "name":name3,
                             "children":[{"id":4,"name":name4}]
                            }
                           ]

似乎不是Object.assign()的方法...它将被覆盖,我不希望覆盖,而是希望它们合并.有正确的方法吗?

Seems like Object.assign() isn't the way to go... as it will overwrite, I do not want it to overwrite, I want them to merge instead. Is there a right way to do this?

推荐答案

Array.prototype.reduce经常为诸如此类的方法提供良好的基础.这一个...

As so often, Array.prototype.reduce provides a good base for an approach like e.g. this one ...

var obj1 = {
  "id": 1,
  "name": "name1",
  "children": [{ "id": 2, "name": "name2" }]
};
var obj2 = {
  "id": 3,
  "name": "name3",
  "children": [{ "id": 4, "name": "name4" }]
};
var obj3 = {
  "id": 1,
  "name": "name1",
  "children": [{ "id": 6, "name": "name6" }]
};
// Expected result: [{
//   "id": 1,
//   "name": name1,
//   "children": [
//     { "id": 2, "name": "name2" },
//     { "id": 6, "name": "name6" }
//   ]
// }, {
//   "id": 3,
//   "name": "name3",
//   "children": [{"id": 4, "name": "name4" }]
// }]

function mergeEquallyLabeledTypes(collector, type) {
  var key = (type.name + '@' + type.id); // identity key.
  var store = collector.store;
  var storedType = store[key];
  if (storedType) { // merge `children` of identically named types.
    storedType.children = storedType.children.concat(type.children);
  } else {
    store[key] = type;
    collector.list.push(type);
  }
  return collector;
}

var result = [obj1, obj2, obj3].reduce(mergeEquallyLabeledTypes, {

  store:  {},
  list:   []

}).list;

console.log('result : ', result);

.as-console-wrapper { max-height: 100%!important; top: 0; }

编辑说明

Edit Note

在获悉了需要处理嵌套模式的变更需求之后,我将把第一个提供的方法变为通用解决方案.由于数据结构中通常存在重复的模式,因此不会那么困难.因此,我只需要使已经存在的reducer函数自递归即可.在任何提供的列表上完成完整的归约循环后,将触发递归步骤...

After having been informed about changed requirements, that need to deal with a nested pattern, I will change my first provided approach into a generic solution. It will be not that difficult since there is a generically repeated pattern within the data structure. Thus I just need to make the already existing reducer function self recursive. A recursion step will be triggered after having finished a complete reducing cycle on any provided list ...

var obj1 = {
  "id": 1,
  "name": "name1",
  "children": [{ "id": 2, "name": "name2", "children": [{ "id": 8, "name": "name8" }] }]
};
var obj2 = {
  "id": 3,
  "name": "name3",
  "children": [{ "id": 4, "name": "name4", "children": [{ "id": 9, "name": "name9" }] }]
};
var obj3 = {
  "id": 1,
  "name": "name1",
  "children": [{ "id": 6, "name": "name6", "children": [{ "id": 10, "name": "name10" }] }]
};
var obj4 = {
  "id": 3,
  "name": "name3",
  "children": [{ "id": 4, "name": "name4", "children": [{ "id": 11, "name": "name11" }] }]
};

function mergeEquallyLabeledTypesRecursively(collector, type, idx, list) {
  var key = (type.name + '@' + type.id); // identity key.
  var store = collector.store;
  var storedType = store[key];
  if (storedType) { // merge `children` of identically named types.
    storedType.children = storedType.children.concat(type.children);
  } else {
    store[key] = type;
    collector.list.push(type);
  }
  // take repetitive data patterns into account ...
  if (idx >= (list.length - 1)) {
    collector.list.forEach(function (type) {

      // ... behave recursive, when appropriate.
      if (type.children) {
        type.children = type.children.reduce(mergeEquallyLabeledTypesRecursively, {

          store:  {},
          list:   []

        }).list;
      }
    });
  }
  return collector;
}

var result = [obj1, obj2, obj3, obj4].reduce(mergeEquallyLabeledTypesRecursively, {

  store:  {},
  list:   []

}).list;

console.log('result : ', result);

.as-console-wrapper { max-height: 100%!important; top: 0; }

这篇关于如何将具有相同属性的对象合并到数组中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆