203 votes

Fusionner 2 tableaux d'objets

Prenons 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 deux tableaux d'objets et créer le tableau suivant :

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

Existe-t-il une fonction JavaScript ou jQuery pour faire cela ?

$.extend ne me convient pas. Il retourne

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

124voto

Jahanzaib Aslam Points 898

Si vous voulez fusionner 2 tableaux d'objets en JavaScript. Vous pouvez utiliser cette astuce en 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"}]

72voto

Nguyễn Bá Vinh Points 639

Avec ES6, vous pouvez le faire très facilement comme ci-dessous :

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

Sortie :

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

55voto

bob Points 736

Pour ceux qui expérimentent des 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"
//     }
// ]

53voto

guya Points 601

Mise à jour du 12 octobre 2019

Nouvelle version basée uniquement sur le nouveau Javascript et ne nécessitant aucune bibliothèque tierce.

const mergeByProperty = (target, source, prop) => {
  source.forEach(sourceElement => {
    let targetElement = target.find(targetElement => {
      return sourceElement[prop] === targetElement[prop];
    })
    targetElement ? Object.assign(targetElement, sourceElement) : target.push(sourceElement);
  })
}
var target /* arr1 */ = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
var source /* arr2 */ = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

mergeByProperty(target, source, 'name');

console.log(target)

Cette réponse commençait à dater, des librairies comme lodash et underscore sont beaucoup moins nécessaires de nos jours. Dans cette nouvelle version, le cible (arr1) array est celui avec lequel nous travaillons et que nous voulons maintenir à jour. Le site source (arr2) est l'endroit d'où proviennent les nouvelles données, et nous voulons qu'elles soient fusionnées avec notre cible le tableau.

Nous bouclons sur le source à la recherche de nouvelles données, et pour chaque objet qui n'est pas encore trouvé dans notre cible nous ajoutons simplement cet objet en utilisant target.push(sourceElement) Si, sur la base de notre propriété clé ('name') Si un objet se trouve déjà dans notre tableau cible, nous mettons à jour ses propriétés et ses valeurs en utilisant la méthode suivante Object.assign(targetElement, sourceElement) . Notre "cible" sera toujours le même tableau, avec un contenu actualisé.


Ancienne réponse utilisant l'underscore ou le lodash

J'arrive toujours ici depuis google et je ne suis toujours pas satisfait des réponses. Votre réponse est bonne mais ce serait plus facile et plus propre d'utiliser underscore.js.

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

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

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);

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"></script>

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

43voto

OwlyMoly Points 891

Très simple en utilisant l'opérateur d'étalement ES6 :

const array1 = [{a: 'HI!'}, {b: 'HOW'}]
const array2 = [{c: 'ARE'}, {d: 'YOU?'}]

const mergedArray = [ ...array1, ...array2 ]
console.log('Merged Array: ', mergedArray)

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Merged Array: [ {a: 'HI!'}, {b: 'HOW'} {c: 'ARE'}, {d: 'YOU?'} ]

Note : La solution ci-dessus consiste à fusionner deux tableaux en utilisant l'opérateur d'étalement ES6.

Modifié le 07 janvier 2020 par @bh4r4th : Le contexte ayant changé en raison des modifications apportées après ma solution initiale. Je voudrais mettre à jour ma solution pour qu'elle corresponde aux critères actuels, c'est-à-dire..,

  1. Fusionner des objets de tableau sans créer d'objets en double et,

  2. mettre à jour le value si le name existe déjà dans le tableau précédent

    const arr1 = [ { name: "lang", value: "English" }, { name: "age", value: "18" } ] const arr2 = [ { name: "childs", value: '2' }, { name: "lang", value: "German" } ] const arr3 = [ { name: "lang", value: "German" }, { name: "age", value: "28" }, { name: "childs", value: '5' } ]

    // Convert to key value dictionary or object const convertToKeyValueDict = arrayObj => { const val = {} arrayObj.forEach(ob => { val[ob.name] = ob.value }) return val }

    // update or merge array const updateOrMerge = (a1, a2) => { const ob1 = convertToKeyValueDict(a1) const ob2 = convertToKeyValueDict(a2) // Note: Spread operator with objects used here const merged_obj = {...ob1, ...ob2} const val = Object.entries(merged_obj) return val.map(obj => ({ name: obj[0], value: obj[1] })) }

    const v1 = updateOrMerge(arr1, arr2) const v2 = updateOrMerge(v1, arr3) console.log(Merged array1 and array2: ${JSON.stringify(v1)} \n\n) console.log(Merged above response and array3: ${JSON.stringify(v2)} \n\n)

    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X