¿Cuál es la mejor / forma estándar de fusionar dos matrices asociativas en JavaScript? ¿Todos lo hacen rodando su propio for
bucle?
¿Cuál es la mejor / forma estándar de fusionar dos matrices asociativas en JavaScript? ¿Todos lo hacen rodando su propio for
bucle?
Respuestas:
con jquery puedes llamar $.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
(las matrices asociadas son objetos en js)
mira aquí: http://api.jquery.com/jQuery.extend/
editar: como sugirió rymo, es mejor hacerlo de esta manera:
obj3 = $.extend({}, obj1, obj2);
obj3 == {a: 4, b: 2, c: 110}
Como aquí, obj1 (y obj2) permanecen sin cambios.
edit2: en 2018 la forma de hacerlo es a través de Object.assign
:
var obj3 = Object.assign({}, obj1, obj2);
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS
Si trabaja con ES6, esto se puede lograr con el Operador de propagación :
const obj3 = { ...obj1, ...obj2 };
obj1
, utilice un objeto vacío como objetivo:$.extend({}, obj1, obj2)
Object.assign()
, que no depende de JQuery si aún no está usando la biblioteca.
Ahora, en 2016, diría que la mejor / estándar es Object.assign ()
Pure Javascript. No se necesita jQuery.
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2); // Object {a: 4, b: 2, c: 110}
Más información, ejemplos y polyfill aquí:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Así es como Prototype lo hace:
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
};
llamado como, por ejemplo:
var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };
var shortnames = Object.extend(arr1,arr2);
EDITAR : se ha agregado la verificación hasOwnProperty () como lo señala correctamente bucabay en los comentarios
Mantenlo simple...
function mergeArray(array1,array2) {
for(item in array1) {
array2[item] = array1[item];
}
return array2;
}
arrau1.prototype
hasOwnProperty
cheque. Hacer referencia a los objetos como matrices también es engañoso (son objetos), los nombres arg deben transmitir que la matriz2 está mutada o que se debe devolver un nuevo objeto. Editaría la respuesta, pero en efecto se convertiría casi exactamente en la respuesta editada de Jonathan Fingland que ya se ha corregido.
El subrayado también tiene un método extendido:
Copie todas las propiedades en los objetos de origen al objeto de destino. Está en orden, por lo que la última fuente anulará las propiedades del mismo nombre en argumentos anteriores.
_.extend(destination, *sources)
_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
En dojo , la combinación de 2 objetos / matrices sería lang.mixin(destination, source)
: también puede mezclar múltiples fuentes en un destino, etc., consulte la referencia de la función mixin para obtener más detalles.
¿Desea sobrescribir una propiedad si los nombres son iguales pero los valores no lo son?
¿Y desea cambiar permanentemente uno de los objetos originales,
o quieres que se devuelva un nuevo objeto combinado?
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???' });
...
Esto simplemente se extiende un splat de objetos, de forma recursiva. Además, tenga en cuenta que esta función recursiva es TCO ( Tail-Call Optimized ) ya que su retorno es la última llamada a sí mismo.
Además, es posible que desee propiedades específicas . En este caso, es posible que desee para condensar los objetos basados en id
, quantity
o de otra propiedad. Este enfoque podría tener un pequeño libro escrito sobre él y requiere yuxtaposición de objetos y puede volverse muy complejo. He escrito una pequeña biblioteca para esto que está disponible a pedido.
¡Espero que esto ayude!
Yahoo UI (YUI) también tiene una función auxiliar para esto:
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 tiene un booleano para copia profunda. Podrías hacer algo así:
MergeRecursive = function(arr1, arr2){
$.extend(true, arr1, arr2);
return arr1;
};
También puede editar esta función para admitir n-arrays para fusionar.
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;
};
Entonces ahora puedes hacer
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);
Necesitaba una fusión profunda de objetos. Así que todas las otras respuestas no me ayudaron mucho. _.extend y jQuery.extend funcionan bien, a menos que tenga una matriz recursiva como yo. Pero no es tan malo, puedes programarlo en cinco minutos:
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;
}
Para fusionar matrices en jQuery, ¿qué pasa con $ .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;
};
Pruebas
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
bloqueare la aplicación.