Regardons un exemple.
var arr1 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
J'ai besoin de 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 le faire?
$ .extend ne me convient pas. Il retourne
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);
Pour ceux qui expérimentent avec 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"
// }
// ]
J'arrive toujours ici de google et je ne suis toujours pas satisfait des réponses. VOUS répondez que c'est bien, mais ce sera plus simple et plus ordonné d'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 '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);
[{name: "lang", valeur: "allemand"}, {name: "age", valeur: "18"}, {name: "childs", valeur: '5'}]
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 'name':
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'}]
Très simple en utilisant l'opérateur ES6 spread:
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?'} ]
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"/>
Avec lodash:
_.uniqBy([...arr1, ...arr2], 'name')
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 veux conserver les éléments qui n'apparaissent pas dans le second tableau, alors j'ai 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'));
Vous pouvez utiliser un objet pour rassembler vos propriétés lors du remplacement des doublons, puis développer/aplatir cet objet pour le transformer en 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 dans arr3
avec "allemand" remplacé par "crêpes".
Cette approche suppose que tous vos objets ont bien sûr la même forme {name: ..., value: ...}
.
Vous pouvez le voir fonctionner ici (ouvrez votre console s'il vous plaît): http://jsfiddle.net/ambiguous/UtBbB/
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"}
]
Je faisais face au même problème et, sur la base de guya answer j’ai étendu la bibliothèque de soulignement et ajouté un peu plus de fonctionnalités que je demandais. 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 vous sera utile!
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}];
Ce problème m'a récemment posé problème et je suis venu ici avec l'espoir d'avoir une réponse, mais la réponse acceptée utilise 2 pour les boucles in que je ne préférerais pas. J'ai finalement réussi à faire 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;
}
}
Ceci maintient également l'ordre d'arr1.
Qu'en est-il de jQuery Merge?
http://api.jquery.com/jQuery.merge/
exemple jsFiddle ici: http://jsfiddle.net/ygByD/
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');
Ici, je filtre d'abord arr1
en fonction de l'élément présent dans arr2
ou non. S'il est présent, ne l'ajoutez pas au tableau résultant, sinon ajoutez-le. Et puis j'ajoute arr2
au résultat.
arr1.filter(item => {
if (!arr2.some(item1=>item.name==item1.name)) {
return item
}
}).concat(arr2)
Utiliser lodash que vous voulez _.uniqBy
var arr3 = _.uniqBy(arr1.concat(arr2), 'name'); // es5
let arr3 = _.uniqBy([...arr1, ...arr2], 'name'); // es6
Ordre d'arr1, arr2 est important!
Voir docs https://lodash.com/docs/4.17.4#uniqBy
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>
(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);
De mémoire - essayez jquery extend
var arr3 = jQuery.extend(arr1,arr2....)
Basé sur la réponse de @ YOU mais en gardant la commande:
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 souhaitez conserver l’ordre tout en mettant à jour les objets.
Si vous souhaitez fusionner les 2 tableaux, mais supprimer les objets en double, utilisez ceci . Les doublons sont identifiés sur .uniqueId
de chaque objet.
function mergeObjectArraysRemovingDuplicates(firstObjectArray, secondObjectArray) {
return firstObjectArray.concat(
secondObjectArray.filter((object) => !firstObjectArray.map((x) => x.uniqueId).includes(object.uniqueId)),
);
}
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;
}
var newArray = yourArray.concat(otherArray);
console.log('Concatenated newArray: ', newArray);
const extend = function*(ls,xs){
yield* ls;
yield* xs;
}
console.log( [...extend([1,2,3],[4,5,6])] );