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

7voto

Vadim Gremyachev Points 2370

Encore une autre version utilisant 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"/>

7voto

marktuk Points 95

Voici comment j'ai abordé un problème similaire dans un contexte ES6 :

function merge(array1, array2, prop) {
    return array2.map(function (item2) {
        var item1 = array1.find(function (item1) {
            return item1[prop] === item2[prop];
        });
        return Object.assign({}, item1, item2);
    });
}

Note : Cette approche ne retournera pas les éléments du tableau 1 qui n'apparaissent pas dans le tableau 2.


EDITAR: J'ai quelques scénarios où je veux préserver les éléments qui n'apparaissent pas dans le deuxième tableau, j'ai donc trouvé une autre méthode.

function mergeArrays(arrays, prop) {
    const merged = {};

    arrays.forEach(arr => {
        arr.forEach(item => {
            merged[item[prop]] = Object.assign({}, merged[item[prop]], item);
        });
    });

    return Object.values(merged);
}

var arr1 = [
    { name: 'Bob', age: 11 },
    { name: 'Ben', age: 12 },
    { name: 'Bill', age: 13 },
];

var arr2 = [
    { name: 'Bob', age: 22 },
    { name: 'Fred', age: 24 },
    { name: 'Jack', age: 25 },
    { name: 'Ben' },
];

console.log(mergeArrays([arr1, arr2], 'name'));

6voto

xgqfrms Points 2718

Jsut utiliser vanilla js (version ES6)

// no need new Array constructor, just using an array literal
const arr1 = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
const arr2 = [{name: "childs", value: '5'}, {name: "lang", value: "German"}];

// 1. create a map
const map = new Map();

// 2. concat array
// arr1.concat(arr2) === [...arr1, ...arr2]
const arr3 = [...arr1, ...arr2];

// 3. for ... of, iterator array
for(const obj of arr3) {
  if(!map.has(obj.name)) {
    // add
    map.set(obj.name, obj);
  } else {
    // update
    map.set(obj.name, {
      ...map.get(obj.name),
      ...obj,
    });
  }
}

// 4. get new merged unqiue array
const arr4 = [...map.values()];

console.log(`result array =`, JSON.stringify(arr4, null, 4));

/*

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

*/

test ✅ (Chrome)

enter image description here

refs

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#array_literals

5voto

ngCourse Points 654

Une solution simple

var tx = [{"id":1},{"id":2}];
var tx1 = [{"id":3},{"id":4}];

var txHistory = tx.concat(tx1)

console.log(txHistory); 
// output
 // [{"id":1},{"id":2},{"id":3},{"id":4}];

4voto

2DH Points 1117

Solution utilisant JS Map :

const merge = (arr1, arr2, prop) => {
    const resultMap = new Map(arr1.map((item) => [item[prop], item]));
    arr2.forEach((item) => {
        const mapItem = resultMap.get(item[prop]);
        if (mapItem) Object.assign(mapItem, item);
        else resultMap.set(item[prop], item);
    });
    return [...resultMap.values()];
};

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

console.log(merge(arr1, arr2, "name"));

Ce qui produit :

merge() function outcome

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