假设您有两个对象:
var foo = {
a : 1,
b : 2
};
var bar = {
a : 3,
b : 4
}
合并它们(并允许深度合并)的最佳方法是创建它:
var foobar = {
a : [1, 3],
b : [2, 4]
}
编辑问题澄清:理想情况下,如果现有属性在一个而不是另一个中,我希望仍然可以创建一个数组,用于规范化目的并允许进一步减少地图,但我在下面看到的答案绰绰有余。出于本练习的目的,我只是寻找字符串或数字合并,所以我没有接受所有可能的情境案例。如果你拿着枪在我的头上然后让我做出选择,我会说默认为阵列。
感谢所有人的贡献。
答案 0 :(得分:9)
这应该做你想要的。它会递归地将任意深度的对象合并到数组中。
// deepmerge by Zachary Murray (dremelofdeath) CC-BY-SA 3.0
function deepmerge(foo, bar) {
var merged = {};
for (var each in bar) {
if (foo.hasOwnProperty(each) && bar.hasOwnProperty(each)) {
if (typeof(foo[each]) == "object" && typeof(bar[each]) == "object") {
merged[each] = deepmerge(foo[each], bar[each]);
} else {
merged[each] = [foo[each], bar[each]];
}
} else if(bar.hasOwnProperty(each)) {
merged[each] = bar[each];
}
}
for (var each in foo) {
if (!(each in bar) && foo.hasOwnProperty(each)) {
merged[each] = foo[each];
}
}
return merged;
}
除了合并的对象将包含继承属性的副本之外,这个会做同样的事情。这可能不是你想要的(根据RobG在下面的评论),但如果这实际上是你正在寻找的,那么它就是:
// deepmerge_inh by Zachary Murray (dremelofdeath) CC-BY-SA 3.0
function deepmerge_inh(foo, bar) {
var merged = {};
for (var each in bar) {
if (each in foo) {
if (typeof(foo[each]) == "object" && typeof(bar[each]) == "object") {
merged[each] = deepmerge(foo[each], bar[each]);
} else {
merged[each] = [foo[each], bar[each]];
}
} else {
merged[each] = bar[each];
}
}
for (var each in foo) {
if (!(each in bar)) {
merged[each] = foo[each];
}
}
return merged;
}
我在http://jsconsole.com上尝试了你的例子,它运行良好:
deepmerge(foo, bar)
{"a": [1, 3], "b": [2, 4]}
bar
{"a": 3, "b": 4}
foo
{"a": 1, "b": 2}
稍微复杂的对象也起作用了:
deepmerge(as, po)
{"a": ["asdf", "poui"], "b": 4, "c": {"q": [1, 444], "w": [function () {return 5;}, function () {return 1123;}]}, "o": {"b": {"t": "cats"}, "q": 7}, "p": 764}
po
{"a": "poui", "c": {"q": 444, "w": function () {return 1123;}}, "o": {"b": {"t": "cats"}, "q": 7}, "p": 764}
as
{"a": "asdf", "b": 4, "c": {"q": 1, "w": function () {return 5;}}}
答案 1 :(得分:3)
据推测,您将迭代一个对象并将其属性名称复制到新对象,并将值复制到分配给这些属性的数组。迭代后续对象,添加属性和数组(如果它们尚不存在)或将它们的值添加到现有属性和数组中。
e.g。
function mergeObjects(a, b, c) {
c = c || {};
var p;
for (p in a) {
if (a.hasOwnProperty(p)) {
if (c.hasOwnProperty(p)) {
c[p].push(a[p]);
} else {
c[p] = [a[p]];
}
}
}
for (p in b) {
if (b.hasOwnProperty(p)) {
if (c.hasOwnProperty(p)) {
c[p].push(b[p]);
} else {
c[p] = [b[p]];
}
}
}
return c;
}
您可以通过迭代所提供的参数来修改它以处理任意数量的对象,但这会使合并的对象更难传递。
答案 2 :(得分:-1)
https://lodash.com/docs/3.10.1#merge
// using a customizer callback
var object = {
'fruits': ['apple'],
'vegetables': ['beet']
};
var other = {
'fruits': ['banana'],
'vegetables': ['carrot']
};
_.merge(object, other, function(a, b) {
if (_.isArray(a)) {
return a.concat(b);
}
});
// → { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }