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() 不是要走的路......因为它会覆盖,我不希望它覆盖,我希望它们合并。有没有正确的方法来做到这一点?
像往常一样,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)