Fusionner 2 tableaux d'objets

Jetez un coup d'œil à un exemple.

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"}); var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"}); 

Je dois fusionner ces 2 tableaux d'objets et créer le tableau suivant.

 arr3 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}); 

Existe-t-il une fonction jScript ou jQuery pour ce faire?

$ .extend ne me convient pas. Il revient

 arr4 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"}); 

Merci d'avance, Alexander.

 var arr3 = []; for(var i in arr1){ var shared = false; for (var j in arr2) if (arr2[j].name == arr1[i].name) { shared = true; break; } if(!shared) arr3.push(arr1[i]) } arr3 = arr3.concat(arr2); 

Entrez la description de l'image ici

Je parviens toujours ici sur Google et je ne suis toujours pas satisfait des réponses. VOUS répondez est bon, mais il sera plus simple et plus simple à utiliser underscore.js

DEMO: http://jsfiddle.net/guya/eAWKR/

Voici une fonction plus générale qui fusionnera 2 tableaux en utilisant une propriété de leurs objets. Dans ce cas, la propriété est "nom"

 var arr1 = [{name: "lang", value: "English"}, {name: "age", value: "18"}]; var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}]; function mergeByProperty(arr1, arr2, prop) { _.each(arr2, function(arr2obj) { var arr1obj = _.find(arr1, function(arr1obj) { return arr1obj[prop] === arr2obj[prop]; }); arr1obj ? _.extend(arr1obj, arr2obj) : arr1.push(arr2obj); }); } mergeByProperty(arr1, arr2, 'name'); console.log(arr1); 

[{Nom: "lang", valeur: "Allemand"}, {nom: "age", valeur: "18"}, {nom: "childs", valeur: '5'}]

Si vous souhaitez fusionner 2 tableaux d'objets en JavaScript. Vous pouvez utiliser cette astuce d'une ligne

Array.prototype.push.apply(arr1,arr2);

Par exemple

 var arr1 = [{name: "lang", value: "English"},{name: "age", value: "18"}]; var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}]; Array.prototype.push.apply(arr1,arr2); console.log(arr1); // final merged result will be in arr1 

Sortie:

 [{"name":"lang","value":"English"}, {"name":"age","value":"18"}, {"name":"childs","value":"5"}, {"name":"lang","value":"German"}] 

Fusion de deux tableaux:

 var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"}); var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"}); var result=arr1.concat(arr2); // result: [{name: "lang", value: "English"}, {name: "age", value: "18"}, {name : "childs", value: '5'}, {name: "lang", value: "German"}] 

Fusionner deux tableaux sans valeurs dupliquées pour 'nom':

 var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"}); var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"}); var i,p,obj={},result=[]; for(i=0;i<arr1.length;i++)obj[arr1[i].name]=arr1[i].value; for(i=0;i<arr2.length;i++)obj[arr2[i].name]=arr2[i].value; for(p in obj)if(obj.hasOwnProperty(p))result.push({name:p,value:obj[p]}); // result: [{name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}] 

Vous pouvez utiliser un objet pour collecter vos propriétés tout en remplaçant les doublons, puis développez / ajustez cet objet à un tableau. Quelque chose comme ça:

 function merge(args) { args = Array.prototype.slice.call(arguments); var o = { }; for(var i = 0; i < args.length; ++i) for(var j = 0; j < args[i].length; ++j) o[args[i][j].name] = args[i][j].value; return o; } function expand(o) { var a = [ ]; for(var p in o) if(o.hasOwnProperty(p)) a.push({ name: p, value: o[p]}); return a; } var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"}); var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"}); var arr3 = expand(merge(arr1, arr2)); 

Je ne sais pas si c'est le moyen le plus rapide, mais cela fonctionne pour n'importe quel nombre de tableaux d'entrée; Par exemple, ceci:

 var a = expand( merge( [{name: "lang", value: "English"}, {name: "age", value: "18"}], [{name: "childs", value: '5'}, {name: "lang", value: "German"}], [{name: 'lang', value: 'Pancakes'}] ) ); 

Vous donne la même chose dans a qui était en arr3 avec "German" remplacé par "Pancakes".

Cette approche suppose que vos objets ont tous le même {name: ..., value: ...} , bien sûr.

Vous pouvez le voir fonctionner ici (ouvrez votre console s'il vous plaît): http://jsfiddle.net/ambiguous/UtBbB/

Pour ceux qui expérimentent les choses modernes:

 var odd = [ { name : "1", arr: "in odd" }, { name : "3", arr: "in odd" } ]; var even = [ { name : "1", arr: "in even" }, { name : "2", arr: "in even" }, { name : "4", arr: "in even" } ]; // ---- // ES5 using Array.filter and Array.find function merge(a, b, prop){ var reduced = a.filter(function(aitem){ return ! b.find(function(bitem){ return aitem[prop] === bitem[prop]; }); }); return reduced.concat(b); } console.log( "ES5", merge(odd, even, "name") ); // ---- // ES6 arrow functions function merge(a, b, prop){ var reduced = a.filter( aitem => ! b.find ( bitem => aitem[prop] === bitem[prop]) ) return reduced.concat(b); } console.log( "ES6", merge(odd, even, "name") ); // ---- // ES6 one-liner var merge = (a, b, p) => a.filter( aa => ! b.find ( bb => aa[p] === bb[p]) ).concat(b); console.log( "ES6 one-liner", merge(odd, even, "name") ); // Results // ( stuff in the "b" array replaces things in the "a" array ) // [ // { // "name": "3", // "arr": "in odd" // }, // { // "name": "1", // "arr": "in even" // }, // { // "name": "2", // "arr": "in even" // }, // { // "name": "4", // "arr": "in even" // } // ] 

Encore une autre version utilisant la reduce() method :

 var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"}); var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"}); var arr = arr1.concat(arr2).reduce(function(prev, current, index, array){ if(!(current.name in prev.keys)) { prev.keys[current.name] = index; prev.result.push(current); } else{ prev.result[prev.keys[current.name]] = current; } return prev; },{result: [], keys: {}}).result; document.getElementById("output").innerHTML = JSON.stringify(arr,null,2); 
 <pre id="output"/> 

Qu'en est-il de jQuery Merge?

http://api.jquery.com/jQuery.merge/

JsFiddle exemple ici: http://jsfiddle.net/ygByD/

J'étais confronté au même problème et basé sur la réponse de Guya, j'ai étendu la bibliothèque de soulignement et ajouté un peu plus de fonctionnalités que j'avais besoin. Voici le Gist .

 /** * Merges two object-like arrays based on a key property and also merges its array-like attributes specified in objectPropertiesToMerge. * It also removes falsy values after merging object properties. * * @param firstArray The original object-like array. * @param secondArray An object-like array to add to the firstArray. * @param keyProperty The object property that will be used to check if objects from different arrays are the same or not. * @param objectPropertiesToMerge The list of object properties that you want to merge. It all must be arrays. * @returns The updated original array. */ function merge(firstArray, secondArray, keyProperty, objectPropertiesToMerge) { function mergeObjectProperties(object, otherObject, objectPropertiesToMerge) { _.each(objectPropertiesToMerge, function (eachProperty) { object[eachProperty] = _.chain(object[eachProperty]).union(otherObject[eachProperty]).compact().value(); }); } if (firstArray.length === 0) { _.each(secondArray, function (each) { firstArray.push(each); }); } else { _.each(secondArray, function (itemFromSecond) { var itemFromFirst = _.find(firstArray, function (item) { return item[keyProperty] === itemFromSecond[keyProperty]; }); if (itemFromFirst) { mergeObjectProperties(itemFromFirst, itemFromSecond, objectPropertiesToMerge); } else { firstArray.push(itemFromSecond); } }); } return firstArray; } _.mixin({ merge: merge }); 

J'espère que cela sera utile! Cordialement!

J'ai récemment été perplexe avec ce problème et je suis venu ici avec l'espoir d'avoir une réponse, mais la réponse acceptée utilise 2 dans les boucles que je ne préférerais pas. J'ai finalement réussi à faire la mienne. Ne dépend d'aucune bibliothèque:

 function find(objArr, keyToFind){ var foundPos = objArr.map(function(ob){ return ob.type; }).indexOf(keyToFind); return foundPos; } function update(arr1,arr2){ for(var i = 0, len = arr2.length, current; i< len; i++){ var pos = find(arr1, arr2[i].name); current = arr2[i]; if(pos !== -1) for(var key in arr2) arr1[pos][key] = arr2[key]; else arr1[arr1.length] = current; } } 

Cela maintient également l'ordre de arr1.

La manière la plus simple est d'avoir une magie ES6:

Fusionnez deux avec des doublons:

 const a = [{a: 1}, {b: 2}] const b = [{a: 1}] const result = a.concat(b) // [{a: 1}, {b: 2}, {a: 1}] 

Sans doublons, il est identique à celui ci-dessus plus:

const distinct = [...new Set(result.map(item => item.YOUR_PROP_HERE))]

Avec lodash :

 var mergedArray = _.concat(arr1, arr2) 

Avec la syntaxe ES6:

 const mergedArray = [...arr1, ...arr2] 

Sur le dessus de ma tête – essayez jquery étendre

 var arr3 = jQuery.extend(arr1,arr2....) 

var newArray = yourArray.concat(otherArray); console.log('Concatenated newArray: ', newArray);

Basé sur la réponse @ YOU, mais en gardant l'ordre:

 var arr3 = []; for(var i in arr1){ var shared = false; for (var j in arr2) if (arr2[j].name == arr1[i].name) { arr3.push(arr1[j] shared = true; break; } if(!shared) arr3.push(arr1[i]) } for(var j in arr2){ var shared = false; for (var i in arr1) if (arr2[j].name == arr1[i].name) { shared = true; break; } if(!shared) arr3.push(arr2[j]) } arr3 

Je sais que cette solution est moins efficace, mais il est nécessaire si vous souhaitez conserver l'ordre et mettre à jour les objets.

Voici un plugin jQuery que j'ai écrit pour fusionner deux tableaux d'objets par une clé. Gardez à l'esprit que cela modifie le tableau de destination en place.

 (function($) { $.extendObjectArray = function(destArray, srcArray, key) { for (var index = 0; index < srcArray.length; index++) { var srcObject = srcArray[index]; var existObject = destArray.filter(function(destObj) { return destObj[key] === srcObject[key]; }); if (existObject.length > 0) { var existingIndex = destArray.indexOf(existObject[0]); $.extend(true, destArray[existingIndex], srcObject); } else { destArray.push(srcObject); } } return destArray; }; })(jQuery); var arr1 = [ { name: "lang", value: "English" }, { name: "age", value: "18" } ]; var arr2 = [ { name: "childs", value: '5' }, { name: "lang", value: "German" } ]; var arr3 = $.extendObjectArray(arr1, arr2, 'name'); console.log(JSON.stringify(arr3, null, 2)); 
 .as-console-wrapper { top: 0; max-height: 100% !important; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

En utilisant lodash vous voulez _.uniqBy

 var arr3 = _.uniqBy(arr1.concat(arr2), 'name'); // es5 let arr3 = _.uniqBy([...arr1, ...arr2], 'name'); // es6 

L'ordre de arr1, arr2 est important!

Voir docs https://lodash.com/docs/4.17.4#uniqBy