Quelle est la meilleure façon / standard de fusionner deux tableaux associatifs en JavaScript? Tout le monde le fait-il simplement en roulant sa propre for
boucle?
Quelle est la meilleure façon / standard de fusionner deux tableaux associatifs en JavaScript? Tout le monde le fait-il simplement en roulant sa propre for
boucle?
Réponses:
avec jquery vous pouvez appeler $.extend
var obj1 = {a: 1, b: 2};
var obj2 = {a: 4, c: 110};
var obj3 = $.extend(obj1, obj2);
obj1 == obj3 == {a: 4, b: 2, c: 110} // Pseudo JS
(les tableaux associés sont des objets dans js)
regardez ici: http://api.jquery.com/jQuery.extend/
edit: Comme Rymo l'a suggéré, il vaut mieux le faire de cette façon:
obj3 = $.extend({}, obj1, obj2);
obj3 == {a: 4, b: 2, c: 110}
Comme ici obj1 (et obj2) restent inchangés.
edit2: En 2018, la façon de le faire est via Object.assign
:
var obj3 = Object.assign({}, obj1, obj2);
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS
Si vous travaillez avec ES6, cela peut être réalisé avec l' opérateur Spread :
const obj3 = { ...obj1, ...obj2 };
obj1
, utilisez un objet vide comme cible:$.extend({}, obj1, obj2)
Object.assign()
, qui ne repose pas sur JQuery si vous n'utilisez pas déjà la bibliothèque.
Maintenant, en 2016, je dirais que le meilleur moyen / standard est Object.assign ()
Pure Javascript. Aucun jQuery n'est nécessaire.
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2); // Object {a: 4, b: 2, c: 110}
Plus d'informations, d'exemples et de polyfill ici:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Voici comment Prototype procède:
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
};
appelé comme, par exemple:
var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };
var shortnames = Object.extend(arr1,arr2);
EDIT : ajout de hasOwnProperty () check comme correctement indiqué par bucabay dans les commentaires
Rester simple...
function mergeArray(array1,array2) {
for(item in array1) {
array2[item] = array1[item];
}
return array2;
}
arrau1.prototype
hasOwnProperty
chèque. Faire référence aux objets en tant que tableaux est également trompeur (ce sont des objets), les noms d'arguments doivent indiquer que array2 est muté ou qu'un nouvel objet doit être retourné. Je modifierais la réponse, mais en fait, elle deviendrait presque exactement la réponse modifiée de Jonathan Fingland qui a déjà été corrigée.
Underscore a également une méthode d'extension:
Copiez toutes les propriétés des objets source dans l'objet de destination. C'est dans l'ordre, donc la dernière source remplacera les propriétés du même nom dans les arguments précédents.
_.extend(destination, *sources)
_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
Dans dojo , la "fusion" à 2 objets / tableaux serait lang.mixin(destination, source)
- vous pouvez également mélanger plusieurs sources dans une seule destination, etc. - voir la référence de la fonction mixin pour plus de détails.
voulez-vous écraser une propriété si les noms sont identiques mais que les valeurs ne le sont pas?
Et voulez-vous changer définitivement l'un des objets d'origine,
ou voulez-vous qu'un nouvel objet fusionné soit renvoyé?
function mergedObject(obj1, obj2, force){
for(var p in obj1) this[p]= obj1[p];
for(var p in obj2){
if(obj2.hasOwnProperty(p)){
if(force || this[p]=== undefined) this[p]= obj2[p];
else{
n= 2;
while(this[p+n]!== undefined)++n;
this[p+n]= obj2[p];
}
}
}
}
function extend(objects) {
var args
, first = Array.prototype.slice.call(arguments, 0, 1)[0]
, second;
if (arguments.length > 1) {
second = Array.prototype.splice.call(arguments, 1, 1)[0];
for (var key in second) {
first[key] = second[key];
}
args = Array.prototype.slice.call(arguments, 0);
return extend.apply(this, args);
}
return first;
}
...
var briansDirections = {
step1: 'Remove pastry from wrapper.',
step2: 'Place pastry toaster.',
step3: 'Remove pastry from toaster and enjoy.',
};
extend(briansDirections, { step1: 'Toast Poptarts' }, { step2: 'Go ahead, toast \'em' }, { step3: 'Hey, are you sill reading this???' });
...
Cela étend simplement un splat d'objets, de manière récursive. Notez également que cette fonction récursive est TCO ( Tail-Call Optimized ) car son retour est le dernier appel à lui-même.
En outre, vous souhaiterez peut-être des propriétés ciblées . Dans ce cas, vous souhaiterez peut-être condenser les objets en fonction de id
,quantity
ou une autre propriété. Cette approche pourrait avoir un petit livre écrit à ce sujet et nécessite une juxtaposition d'objets et peut devenir très complexe. J'ai écrit une petite bibliothèque pour cela qui est disponible sur demande.
J'espère que cela t'aides!
En 2019, vous avez 2 bonnes options:
Attribution d'objets [ doc ]
const result = Object.assign({}, baseObject, updatingObject);
Répartition d'objets [ doc ]
const result = { ...baseObject, ...updatingObject};
Le premier a tendance à être plus sûr, plus standard et polyvalent. Un bon pour et contre ici
Yahoo UI (YUI) a également une fonction d'assistance pour cela:
http://developer.yahoo.com/yui/examples/yahoo/yahoo_merge.html
YAHOO.namespace('example');
YAHOO.example.set1 = { foo : "foo" };
YAHOO.example.set2 = { foo : "BAR", bar : "bar" };
YAHOO.example.set3 = { foo : "FOO", baz : "BAZ" };
var Ye = YAHOO.example;
var merged = YAHOO.lang.merge(Ye.set1, Ye.set2, Ye.set3);
jquery a un booléen pour la copie profonde. Vous pourriez faire quelque chose comme ça:
MergeRecursive = function(arr1, arr2){
$.extend(true, arr1, arr2);
return arr1;
};
Vous pouvez également modifier cette fonction pour prendre en charge les n-tableaux à fusionner.
ArrayMergeRecursive = function(){
if(arguments.length < 2){
throw new Error("ArrayMergeRecursive: Please enter two or more objects to merge!");
}
var arr1=arguments[0];
for(var i=0; i<=arguments.length; i++ ){
$.extend(true, arr1, arguments[i]);
}
return arr1;
};
Alors maintenant tu peux faire
var arr1 = {'color': {'mycolor': 'red'}, 3: 5},
arr2 = {4: 10, 'color': {'favorite': 'green', 0: 'blue'}},
arr3 = ['Peter','Jhon','Demosthenes'],
results = ArrayMergeRecursive(arr1, arr2, arr3); // (arr1, arr2 ... arrN)
console.log("Result is:", results);
J'avais besoin d'une fusion d'objets en profondeur. Donc, toutes les autres réponses ne m'ont pas beaucoup aidé. _.extend et jQuery.extend fonctionnent bien, à moins que vous n'ayez un tableau récursif comme moi. Mais ce n'est pas si grave, vous pouvez le programmer en cinq minutes:
var deep_merge = function (arr1, arr2) {
jQuery.each(arr2, function (index, element) {
if (typeof arr1[index] === "object" && typeof element === "object") {
arr1[index] = deep_merge(arr1[index], element);
} else if (typeof arr1[index] === "array" && typeof element === "array") {
arr1[index] = arr1[index].concat(element);
} else {
arr1[index] = element;
}
});
return arr1;
}
Pour fusionner des tableaux dans jQuery, qu'en est-il de $ .merge?
var merged = $.merge([{id:3, value:'foo3'}], [{id:1, value:'foo1'}, {id:2, value:'foo2'}]);
merged[0].id == 3;
merged[0].value == 'foo3';
merged[1].id == 1;
merged[1].value == 'foo1';
merged[2].id == 2;
merged[2].value == 'foo2';
var addProps = function (original, props) {
if(!props) {
return original;
}
if (Array.isArray(original)) {
original.map(function (e) {
return addProps(e, props)
});
return original;
}
if (!original) {
original = {};
}
for (var property in props) {
if (props.hasOwnProperty(property)) {
original[property] = props[property];
}
}
return original;
};
Des tests
console.log(addProps([{a: 2}, {z: 'ciao'}], {timestamp: 13}));
console.log(addProps({single: true}, {timestamp: 13}));
console.log(addProps({}, {timestamp: 13}));
console.log(addProps(null, {timestamp: 13}));
[ { a: 2, timestamp: 13 }, { z: 'ciao', timestamp: 13 } ]
{ single: true, timestamp: 13 }
{ timestamp: 13 }
{ timestamp: 13 }
Object.getOwnPropertyNames is not a function
je planterai l'application.