Je dois combiner deux tableaux JSON, fournis par deux services de repos. Les entrées avec le même "id" vont de pair.
json1 = [{id:1,name:'aaa'},
{id:5,name:'ccc'},
{id:3,name:'bbb'}
];
json2 = [{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
{id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
{id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
];
J'ai besoin d'un tableau json combiné/copié/cloné en javascript de la manière suivante (mon modèle en angular2):
json3 = [{id:3,name:'bbb',parameter1:'x', parameter2:'y', parameter3:'z'},
{id:1,name:'aaa', parameter1:'u', parameter2:'v', parameter3:'w'},
{id:5,name:'ccc', parameter1:'q', parameter2:'w', parameter3:'e'}
];
Y a-t-il un moyen de les combiner? Les noms de paramètre ne sont pas définis exactement et il doit fonctionner avec des vecteurs de paramètre variables.
Je l'ai essayé avec mixte pour chaque boucles. Cela me semble très moche.
Si vous voulez l'écrire de manière à pouvoir prendre n'importe quel nombre de tableaux, pas seulement 2, vous pouvez utiliser arguments et faire quelque chose comme ça:
var json1 = [{id:1,name:'aaa'},{id:5,name:'ccc'},{id:3,name:'bbb'}];
var json2 = [{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
{id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
{id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
];
function joinObjects() {
var idMap = {};
// Iterate over arguments
for(var i = 0; i < arguments.length; i++) {
// Iterate over individual argument arrays (aka json1, json2)
for(var j = 0; j < arguments[i].length; j++) {
var currentID = arguments[i][j]['id'];
if(!idMap[currentID]) {
idMap[currentID] = {};
}
// Iterate over properties of objects in arrays (aka id, name, etc.)
for(key in arguments[i][j]) {
idMap[currentID][key] = arguments[i][j][key];
}
}
}
// Push properties of idMap into an array
var newArray = [];
for(property in idMap) {
newArray.Push(idMap[property]);
}
return newArray;
}
var json3 = joinObjects(json1, json2);
Deux one-liners:
avec lodash:
res = _(json1).concat(json2).groupBy('id').map(_.spread(_.assign)).value();
dans ES2015:
res = json2.map(x => Object.assign(x, json1.find(y => y.id == x.id)));
La réponse d'ES2015 georg fonctionne très bien;
json1 = [
{id:1, test: 0},
{id:2, test: 0},
{id:3, test: 0},
{id:4, test: 0},
{id:5, test: 0}
];
json2 = [
{id:1, test: 1},
{id:3, test: 1},
{id:5, test: 1}
];
json1.map(x => Object.assign(x, json2.find(y => y.id == x.id)));
résultat:
{id:1, test: 1},
{id:2, test: 0},
{id:3, test: 1},
{id:4, test: 0},
{id:5, test: 1}
Utilisez des boucles imbriquées pour rechercher les éléments correspondants et les fusionner.
for (var i = 0; i < json1.length; i++) {
var id = json1[i].id;
for (var j = 0; j < json2.length; j++) {
if (json2[j].id = id) {
for (var key in json2[j]) {
json1[i][key] = json2[j][key];
}
break;
}
}
}
À la fin, json1
contiendra les éléments combinés.
Le code ci-dessus suppose que chaque élément de json2
correspond à quelque chose dans json1
. S'il peut y avoir des éléments supplémentaires dans json2
, vous aurez besoin d'une boucle supplémentaire par la suite pour les copier dans json1
.
Utilisez pourChaque et filtre nous pouvons résoudre le problème.
vehicleArray1 = [{id:1, name: "a"},{id:2, name: "b"},{id:3, name:"c"}];
vehicleArray2 = [{id:1, type: "two wheeler"},{id:2, type: "four wheeler"},{id:3, type:"six wheeler"}];
var outArr = [];
vehicleArray1.forEach(function(value) {
var existing = vehicleArray2.filter(function(v, i) {
return (v.id == value.id);
});
if (existing.length) {
value.type = existing[0].type;
outArr.Push(value)
} else {
value.type = '';
outArr.Push(value);
}
});
console.log(outArr)
Voici un moyen de créer un index à clé id (tableau fragmenté) pour détecter et combiner des objets avec des valeurs id correspondantes, qui sont ensuite concaténés dans un tableau normal:
json3 = json1.concat(json2).reduce(function(index, obj) {
if (!index[obj.id]) {
index[obj.id] = obj;
} else {
for (prop in obj) {
index[obj.id][prop] = obj[prop];
}
}
return index;
}, []).filter(function(res, obj) {
return obj;
});
json1 = [
{id:1,name:'aaa'},
{id:5,name:'ccc'},
{id:3,name:'bbb'}
];
json2 = [
{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
{id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
{id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
];
json3 = json1.concat(json2).reduce(function(index, obj) {
if (!index[obj.id]) {
index[obj.id] = obj;
} else {
for (prop in obj) {
index[obj.id][prop] = obj[prop];
}
}
return index;
}, []).filter(function(res, obj) {
return obj;
});
document.write('<pre>', JSON.stringify(json3, null, 4), '</pre>');
Si votre navigateur prend en charge Object.assign :
json3 = json1.concat(json2).reduce(function(index, obj) {
index[obj.id] = Object.assign({}, obj, index[obj.id]);
return index;
}, []).filter(function(res, obj) {
return obj;
});
Cela devrait le faire pour vous. J'espère que le code a un sens en soi. Cet exemple utilisera toujours la valeur json1
par rapport à la valeur json2
si les deux existent. Si vous voulez changer cela, vous devez changer les références d'objet (src[i]
et obj[j]
) dans la boucle la plus interne.
// Will take src, and merge in the contents of obj.
// Expects an array of objects for both.
// Will keep src values in favour of obj values.
function extend(src, obj) {
// Loop the src, in this case json1
for (var i = 0; i < src.length; i++) {
// For every loop of json1, also loop json2
for (var j = 0; j < obj.length; j++) {
// If we have matching IDs operate on this pair
if (src[i].id == obj[j].id) {
// For every key in the object being merged in,
// if the key exists in src, ignore new value.
// if the doesn't exist in src, take the new value.
for (var key in obj[j]) {
src[i][key] = src[i].hasOwnProperty(key) ? src[i][key] : obj[j][key];
}
// We found our matching pair, so break out of the json2 loop
break;
}
}
}
return src;
}
// -------------------------------------------
var json1 = [{
id: 1,
name: 'aaa'
},{
id: 5,
name: 'ccc'
},{
id: 3,
name: 'bbb'
}];
var json2 = [{
id: 3,
parameter1: 'x',
parameter2: 'y',
parameter3: 'z'
},{
id: 1,
parameter1: 'u',
parameter2: 'v',
parameter3: 'w'
},{
id: 5,
parameter1: 'q',
parameter2: 'w',
parameter3: 'e'
}];
var json3 = extend(json1, json2);
// ---------------------------------------------
var pre = document.getElementById('out');
pre.innerHTML = JSON.stringify(json3);
<pre id="out"></pre>