Fusionner 2 tableaux d'objets

112

Jetons un œ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 JavaScript ou jQuery pour faire cela?

$.extendne me convient pas. Il retourne

arr4 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
Alexandre
la source
15
Qu'est-il arrivé {name: "lang", value: "English"}?
Shadow Wizard est une oreille pour vous
Désolé. Je mentionne $ .extend, pas $ .merge.
Alexander
1
Je veux dire, quelle est la logique impliquée? Comment voulez-vous fusionner les tableaux? Ce n'est pas clair d'après vos exemples.
Shadow Wizard est une oreille pour vous
Merci beaucoup à tous. Je l'ai fait manuellement.
Alexander
6
@ShadowWizard, je pense que ce que l'OP signifiait était de mettre à jour s'il existe et de pousser si non.
Amin Mohamed Ajani du

Réponses:

84

Si vous souhaitez 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

Production:

[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]
Jahanzaib Aslam
la source
C'est jusqu'à présent l'utilisation la plus simple et fonctionne très bien. Merci de l'avoir partagé.
Leo Caseiro
17
même résultat que le beaucoup plus simple:arr1 = arr1.concat(arr2)
keithpjolley
7
mais ce n'est pas fusionner!
Dimitri Kopriwa
1
Les résultats ne sont pas les mêmes. concatrenverra un nouveau tableau et cassera toutes les références que vous aviez.
Bpainter le
8
Cela ne répond pas à la question, le tableau résultant doit avoir 3 objets, pas 4. Vous avez modifié les valeurs d'exemple. Fondamentalement, ce que souhaite OP est de fusionner deux tableaux d'objets et de supprimer les valeurs en double.
Ranjan
43

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

Production:

    arr3 = [
      {"name":"lang","value":"German"},
      {"name":"age","value":"18"},
      {"name":"childs","value":"5"},
      {"name":"lang","value":"German"}
    ]
Nguyễn Bá Vinh
la source
6
Cela devrait être la meilleure réponse.
nocdib
20
Cela ne fait pas ce que l'OP recherchait, il ne devrait pas y avoir un deuxième objet contenant{ name: 'lang', value: 'German'}
Will
3
Je ne sais pas pourquoi cette réponse est votée. Ce que @ daveanderson88 veut est différent de cette réponse.
Nguyễn Xuân Hoàng
33

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"
//     }
// ]
bob
la source
29

Mise à jour du 12 octobre 2019

Nouvelle version basée uniquement sur le nouveau Javascript et sans avoir besoin d'une 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 vieillissait, les bibliothèques comme lodash et le soulignement sont beaucoup moins nécessaires de nos jours. Dans cette nouvelle version, le tableau cible (arr1) est celui avec lequel nous travaillons et que nous souhaitons maintenir à jour. Le tableau source (arr2) est l'endroit d'où proviennent les nouvelles données, et nous voulons qu'elles soient fusionnées dans notre cible tableau .

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


Ancienne réponse utilisant un trait de soulignement ou un lodash

J'arrive toujours ici de google et je ne suis toujours pas satisfait des réponses. VOTRE réponse est bonne, mais ce sera plus facile et plus net en utilisant underscore.js

DÉMO: 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);
<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'}]
guya
la source
6
Presque identique en LOC, complexité comme la réponse de @ YOU, sauf que c'est beaucoup plus lent (en grande partie à cause des appels de fonctions supplémentaires et du fait que la réponse de YOU exploite l'astuce des tableaux associatifs JS pour trouver des éléments avec la recherche O (1)). Ceci est en plus du fait que vous devez apporter une bibliothèque supplémentaire.
Mrchief
Vous n'obtiendrez aucune différence de performances à moins que vous ne traitiez des cas extrêmes. En ce qui concerne le supplément lib - underscore, lodash et autres sont généralement déjà utilisés et ont d'autres avantages, il faut envisager de l'utiliser de toute façon. La plupart des développeurs et des applications bénéficieront de la simplicité et de la généralité de cette solution.
guya
1
@guya Je me rends compte que c'est vieux mais le soulignement, le lodash et autres sont généralement déjà utilisés et ont d'autres avantages alors que comme vous le dites, ils ont d'autres avantages, c'est une énorme hypothèse de dire qu'ils sont généralement déjà utilisés.
Craicerjack
26
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

TU
la source
1
Cette réponse a une mauvaise complexité temporelle (O (n ^ 2)). Une solution O (n) est possible en utilisant une carte de hachage.
Alex von Brandenfels
19

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?'} ]

Remarque: La solution ci-dessus consiste simplement à fusionner deux tableaux à l'aide de l'opérateur de propagation ES6.

Edit le 07 janvier 2020 par @ bh4r4th: Comme le contexte a changé en raison de modifications après ma solution initiale. Je souhaite mettre à jour ma solution pour qu'elle corresponde aux critères actuels. c'est à dire,

  1. Fusionner les objets du tableau sans créer d’objets dupliqués et,

  2. mettre à jour valuesi la namepropriété 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>

bh4r4th
la source
1
Cela devrait être la réponse acceptée en 2019! J'allais proposer la même solution après avoir examiné les autres réponses avec un nombre de voix plus élevé! @Alexander C'est facile à rater mais merci d'accepter celui-ci!
iaforek le
Incorrect. Le questionneur veut spécifiquement REMPLACER les objets s'ils ont une propriété dupliquée, pas simplement les ajouter.
HaveSpacesuit
Merci d'avoir indiqué @HaveSpacesuit. J'ai répondu à cette question en 2018 lorsque le contexte consiste simplement à fusionner deux tableaux. Éditera bientôt cette réponse pour l'utiliser setlors de la fusion pour supprimer les doublons. Cela créerait un nouvel argument variable mais un code minimal. Cependant, je ne suis pas un grand fan de la charge utile qui a des noms définis comme des propriétés et des valeurs comme des types différents. Au lieu de cela, je préfère [ { lang: &#39;German&#39;, age: 25}] . De cette façon, le poids de la charge utile sera minimisé lors de la communication entre les services.
bh4r4 le
J'ai maintenant mis à jour la solution pour qu'elle corresponde au nouveau contexte de la question.
bh4r4th
16

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"}]

Fusion de 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'}]
Andrew D.
la source
Array.concat est la bonne façon de fusionner 2 tableaux en un seul. J'aime aussi l'hypothèse étendue selon laquelle le concept de "vraie" fusion a été traité (basé sur une clé donnée de chaque élément du tableau).
bob
14

Le moyen le plus simple est avec un peu de magie ES6:

Fusionner 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, c'est la même chose que ci-dessus plus:

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

Knikolov
la source
1
concat ne fonctionne pas avec des éléments de natures différentes
fdsfdsfdsfds
7

Avec lodash:

_.uniqBy([...arr1, ...arr2], 'name')
Pietro
la source
que la syntaxe ES6 fonctionne avec 2 tableaux, pas avec 2 tableaux d'objets.
Dario
7

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

Remarque: cette approche ne renverra aucun élément de array1 qui n'apparaît pas dans array2.


EDIT: J'ai des scénarios dans lesquels je souhaite conserver les éléments qui n'apparaissent pas dans le deuxième tableau, j'ai donc proposé 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'));
Marktuk
la source
6

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"/>

Vadim Gremyachev
la source
Cela a très bien fonctionné pour moi. Un petit problème est que l'ordre est parfois étrange lors de la fusion de 3 grands objets
Json
5

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}];
Shashwat Gupta
la source
4

Vous pouvez utiliser un objet pour collecter vos propriétés tout en remplaçant les doublons, puis développer / aplatir cet objet en 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 en ce aqui était enarr3 avec "allemand" remplacé par "crêpes".

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

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

mu est trop court
la source
2

Qu'en est-il de jQuery Merge?

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

Exemple jsFiddle ici: http://jsfiddle.net/ygByD/

321X
la source
Cela ne remplacera pas l'anglais par l'allemand comme spécifié, la fusion se déroule le long des namepropriétés.
mu est trop court
AH ouais, tu as raison! Je n'ai pas vu cette spécification en un coup d'œil!
321X
+1. Bien! d'autre part, c'est une très bonne fonction de fusionner des tableaux d'objets javascript
Muhammad Raheel
2

J'étais confronté au même problème et sur la base de la réponse guya, j'ai étendu la bibliothèque de soulignements et ajouté un peu plus de fonctionnalités dont j'avais besoin. Voici l' essentiel .

/**
 * 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 vous sera utile! Cordialement!

Nahuel Barrios
la source
2

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 pour des boucles que je ne préférerais pas. J'ai finalement réussi à créer le mien. 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.

Amin Mohamed Ajani
la source
2

vous pouvez utiliser la fonction suivante

const merge = (a, b, key = "id") =>
  a.filter(elem => !b.find(subElem => subElem[key] === elem[key]))
   .concat(b);

et essaye

merge(arr1, arr2, 'name');
Diogo Alves
la source
Grâce à la manière Diago avec la fonctionnalité immuable ES6 `` `` export const mergeArrays = (a1, a2, key = "id") => a1 && a2! = Null? [... a1.filter (a =>! a2.find (p => p [clé] === a [clé])), ... a2]: null; ``
Musa
1

Ici, je filtre d'abord en arr1fonction de l'élément présent arr2ou non. S'il est présent, ne l'ajoutez pas au tableau résultant, sinon ajoutez. Et puis j'ajoute arr2au résultat.

arr1.filter(item => {
  if (!arr2.some(item1=>item.name==item1.name)) {
    return item
  }
}).concat(arr2)
maulik bhatt
la source
Veuillez fournir l'explication de votre réponse. Donc, si une autre personne lit la question et la réponse, elle peut facilement la comprendre.
Mittal Patel
Bien que cette réponse soit probablement correcte et utile, il est préférable que vous y incluiez des explications pour expliquer comment elle aide à résoudre le problème. Cela devient particulièrement utile à l'avenir, s'il y a un changement (peut-être sans rapport) qui l'empêche de fonctionner et que les utilisateurs doivent comprendre comment cela fonctionnait autrefois.
Erty Seidohl
Merci les gars. J'ai mis à jour la description de la solution. Si cela semble correct pls upvote :)
maulik bhatt
0

Du haut de ma tête - essayez jquery extend

var arr3 = jQuery.extend(arr1,arr2....)
Xhalent
la source
Désolé. Exactement cette fonction renvoie arr4. Pas $ .merge. Le dernier ne me convient pas non plus, car il duplique des objets.
Alexander
0

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

javaScriptBeard
la source
Je conviens que cela a beaucoup plus de sens que la Array.protype.push.apply()réponse, mais cela ne fait pas la fusion comme OP le voulait.
keithpjolley
vous ne pouvez pas obtenir la sortie ci-dessus en utilisant 'concat' si vous avez deux tableaux de fusion d'objets. Veuillez vérifier ceci sur jsfiddle.net/jahanzaibaslam/z22n5tuo
Jahanzaib Aslam
0

Basé sur la réponse de @ 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 elle est nécessaire si vous voulez garder l'ordre et quand même mettre à jour les objets.

hcarreras
la source
0

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 sur 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>


Version ES6

(function($) {
  $.extendObjectArray = (destArr, srcArr, key) => {
    srcArr.forEach(srcObj => (existObj => {
      if (existObj.length) {
        $.extend(true, destArr[destArr.indexOf(existObj[0])], srcObj);
      } else {
        destArr.push(srcObj);
      }
    })(destArr.filter(v => v[key] === srcObj[key])));
    return destArr;
  };
})(jQuery);
M. Polywhirl
la source
0

Utilisation de lodash que vous voulez _.uniqBy

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

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

Ordre de arr1, arr2 compte!

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

danday74
la source
besoin d'utiliser un tiers?
Nguyễn Xuân Hoàng
non mais c'est le moyen le plus concis d'y parvenir, et ce n'est pas n'importe quel tiers, son lodash!
danday74
0
const extend = function*(ls,xs){
   yield* ls;
   yield* xs;
}

console.log( [...extend([1,2,3],[4,5,6])]  );
codemonkey
la source
2
Ne répondez tout simplement pas à la question. Expliquez également comment cette solution résout le problème.
Mittal Patel
0
merge(a, b, key) {
    let merged = [];
    a.forEach(aitem => {
        let found = b.find( bitem => aitem[key] === bitem[key]);
        merged.push(found? found: aitem);
    });
    return merged;
}
Kyaw
la source
0

Si vous souhaitez fusionner les 2 tableaux, mais supprimer les objets en double, utilisez ceci. Les doublons sont identifiés sur .uniqueIdchaque objet

function mergeObjectArraysRemovingDuplicates(firstObjectArray, secondObjectArray) {
  return firstObjectArray.concat(
    secondObjectArray.filter((object) => !firstObjectArray.map((x) => x.uniqueId).includes(object.uniqueId)),
  );
}
daveanderson88
la source
0

Essaye ça:

var a = [{"a":20, "b":10,"c":"c","d":"asd","f":"any"}]
var b = [{"a":20, "b":10,"c":"c", "e":"nan","g":10200}]

var p = []
_.map(a, function(da){
var chk = _.filter(b, function(ds){
return da.a ===ds.a
})[0]
p.push(_.extend(da, chk))


})

console.log(p)

OutPut sera:

  [{
    "a": 20,
    "b": 10,
    "c": "c",
    "d": "asd",
    "f": "any",
    "e": "nan",
    "g": 10200
  }]
Rohit Parte
la source
0
const arr1 = ["Vijendra","Singh"];
const arr2 = ["Singh", "Shakya"];

arr2.forEach(item => {
        if(!arr1.find(k => k===item))
          arr1.push(item)
    });


console.log(arr1)
Gajju
la source
0

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:

résultat de la fonction merge ()

2DH
la source
0
const array1 = [{id:1,name:'ganza'},
{id:2,name:'respice dddd'},{id:4,name:'respice dddd'},{id:6,name:'respice dddd'},
{id:7,name:'respice dddd'}];
const array2 = [{id:1,name:'ganza respice'},{id:2,name:'respice'},{id:3,name:'mg'}];

 function mergeTwoArray(array1,array2){

    return array1.map((item,i)=>{
        if(array2[i] && item.id===array2[i].id){
          return array2[i];
          }else{
            return item;
          }
    });
  }

const result = merge(array1,array2);
console.log(result);
//here is the result:  Array [Object { id: 1, name: "ganza respice" }, Object { id: 2, name: "respice" }, Object { id: 4, name: "respice dddd" }, Object { id: 6, name: "respice dddd" }, Object { id: 7, name: "respice dddd" }]
Ganza respice
la source