我正在尝试合并其中包含数组和其他元素的两个javascript对象。我举个例子。
{
"addresses": [
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai1@gmail.com"
},
{
"type": "phone",
"tags": [
"Responsável",
"Mãe"
],
"address": "551138839332"
},
{
"type": "email",
"tags": [
"Mãe"
],
"address": "johndoemae1@gmail.com"
},
{
"type": "email",
"tags": [
"Aluno"
],
"address": "johndoealuno1@gmail.com"
}
],
"class": [
"Sala 1",
"Sala 2",
"Sala 3"
],
"fullname": "John Doe 1",
"eid": "2",
"invisible": true,
"see_all": false
},
{
"addresses": [
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai2@gmail.com"
},
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai3@gmail.com"
},
{
"type": "phone",
"tags": [
"Pai"
],
"address": "5519985504400"
},
{
"type": "phone",
"tags": [
"Responsável",
"Mãe"
],
"address": "551138839333"
},
{
"type": "email",
"tags": [
"Mãe"
],
"address": "11 983340440"
},
{
"type": "email",
"tags": [
"Aluno"
],
"address": ""
}
],
"class": [
"Sala 4",
"Sala 5",
"Sala 6"
],
"fullname": "John Doe 1",
"eid": "2",
"invisible": false,
"see_all": true
}
正如您所看到的,我们可以在内部包含一些数组中的字符串。 我尝试使用一些递归来做,但没有成功。
function mergeObjects(target, source){
var item, tItem, o, idx;
if (typeof source == 'undefined') {
return source;
} else if (typeof target == 'undefined') {
return target;
}
for (var prop in source) {
item = source[prop];
//check if the first element is indeed an object.
if (typeof item == 'object' && item !== null) {
//if the first item is an array
if (_.isArray(item) && item.length) {
//dealing with array of primitives
if (typeof item[0] != 'object') {
item.forEach(function(conteudo){
//push to the target all the elements;
target[prop].push(conteudo);
});
}else{
//dealing with array of objects;
for(var attr in item){
idx = {};
tItem = target[attr]
mergeObjects(tItem,item);
}
}
}//if its a normal object
else {
// deal with object
mergeObjects(target[prop],item);
}
} else {
// item is a primitive, just copy it over
target[prop] = item;
}
}
return target;
}
我期待这个:
{
"addresses": [
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai2@gmail.com"
},
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai3@gmail.com"
},
{
"type": "phone",
"tags": [
"Pai"
],
"address": "5519985504400"
},
{
"type": "phone",
"tags": [
"Responsável",
"Mãe"
],
"address": "551138839333"
},
{
"type": "email",
"tags": [
"Mãe"
],
"address": "11 983340440"
},
{
"type": "email",
"tags": [
"Aluno"
],
"address": ""
}
],
"class": [
"Sala 4",
"Sala 5",
"Sala 6",
"Sala 1",
"Sala 2",
"Sala 3"
],
"fullname": "John Doe 1",
"eid": "2",
"invisible": true,
"see_all": false
}
"fullname": "John Doe 1",
"eid": "1234",
"classes": [
"Sala 1",
"Sala 2",
"Sala 3",
"Sala 4",
"Sala 5",
"Sala 6"
],
"addresses": [{
"type": "phone",
"tags": [
"Responsável",
"Mãe"
],
"address": "551138839332"
}, {
"type": "email",
"tags": [
"Mãe"
],
"address": "johndoemae1@gmail.com"
}, {
"type": "email",
"tags": [
"Aluno"
],
"address": "johndoealuno1@gmail.com"
}, {
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai2@gmail.com"
}, {
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai3@gmail.com"
}, {
"type": "phone",
"tags": [
"Pai"
],
"address": "5519985504400"
}, {
"type": "phone",
"tags": [
"Responsável",
"Mãe"
],
"address": "551138839333"
}],
"invisible": true,
"see_all": true
}
但我得到的是,正如你所看到的,有些电子邮件元素丢失了。
{
"addresses": [
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai2@gmail.com"
},
{
"type": "email",
"tags": [
"Responsável",
"Pai"
],
"address": "johndoepai3@gmail.com"
},
{
"type": "phone",
"tags": [
"Pai"
],
"address": "5519985504400"
},
{
"type": "phone",
"tags": [
"Responsável",
"Mãe"
],
"address": "551138839333"
},
{
"type": "email",
"tags": [
"Mãe"
],
"address": "11 983340440"
},
{
"type": "email",
"tags": [
"Aluno"
],
"address": ""
}
],
"class": [
"Sala 4",
"Sala 5",
"Sala 6",
"Sala 1",
"Sala 2",
"Sala 3"
],
"fullname": "John Doe 1",
"eid": "2",
"invisible": true,
"see_all": false
}
元素顺序不是问题 我错过了递归树的哪一点?
答案 0 :(得分:1)
简短回答:你必须先自己合并数组。或者你可以使用像Lodash's mergeWidth Ramda's R.mergeWith这样的好东西(参见下面的Ramda示例代码)。
你想要的东西就像本机的Object.assign(有限的浏览器支持,所以它必须是polyfilled)或者你的JS库有什么合并。
您遇到的问题是所有这些合并实现如何处理重复键。通常,密钥将设置为传入的最后一个值:
var thing1 = {
someProperty: 'foo'
};
var thing2 = {
someProperty: 'bar'
};
var result1 = Object.assign({}, thing1, thing2);
// -> {someProperty: 'bar'} (set to the last value passed in, in thing2)
var result2 = Object.assign({}, thing2, thing1);
// -> {someProperty: 'foo'} (again set to the last value passed in, in thing1)
// Make the Stackoverflow snippet display the output.
document.body.innerHTML += JSON.stringify(result1, null, 2);
document.body.innerHTML += '<br>' + JSON.stringify(result2, null, 2);
与您的示例以相同的方式工作,除了属性是一个更复杂的数组。它被设置为传入的最后一个数组:
var thing1 = {
someList: [1, 2, 3]
};
var thing2 = {
someList: [4, 5, 6]
};
var result = Object.assign({}, thing1, thing2);
// -> {someList: [4, 5, 6]}
// Make the Stackoverflow snippet display the output.
document.body.innerHTML = JSON.stringify(result, null, 2);
如果你使用像Ramda这样的东西,你可以合并并指定一个函数来控制键相等时的行为,就像你的情况一样。在这里,我们可以检查值是否为数组,然后连接,如果是这样。否则,返回最新值(如上所述):
var thing1 = {someList: [1, 2, 3]};
var thing2 = {someList: [4, 5, 6]};
var dupeMergeFn = function(a, b) {
return (Array.isArray(a)) ? a.concat(b) : b;
};
var result = R.mergeWith(dupeMergeFn, thing1, thing2);
// Make the Stackoverflow snippet display the output.
document.body.innerHTML = JSON.stringify(result, null, 2);
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.19.1/ramda.min.js"></script>