如何将具有相同属性的对象合并到一个数组中?

Ron*_*ldo 4 javascript arrays tree recursion data-structures

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

以此为例:

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);
Run Code Online (Sandbox Code Playgroud)

预期结果:

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}]
                           }
                          ]
Run Code Online (Sandbox Code Playgroud)

实际结果:

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

似乎 Object.assign() 不是要走的路......因为它会覆盖,我不希望它覆盖,我希望它们合并。有没有正确的方法来做到这一点?

Pet*_*ger 6

像往常一样,Array.prototype.reduce为诸如此类的方法提供了良好的基础......

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);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100%!important; top: 0; }
Run Code Online (Sandbox Code Playgroud)

编辑笔记

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

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);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100%!important; top: 0; }
Run Code Online (Sandbox Code Playgroud)