Каков наилучший/стандартный способ слияния двух ассоциативных массивов в JavaScript? Все ли это делают, перевернув собственный цикл for
?
Объединение объектов (ассоциативных массивов)
Ответ 1
с jquery вы можете вызвать $.extend
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = $.extend(obj1, obj2);
obj1 == obj3 == {a: 4, b: 2, c: 110}
(ассоциативные массивы - объекты в js)
смотрите здесь: http://api.jquery.com/jQuery.extend/
edit: Как и предложил реймо, лучше сделать так:
obj3 = $.extend({}, obj1, obj2);
obj3 == {a: 4, b: 2, c: 110}
Как здесь obj1 (и obj2) остаются неизменными.
Ответ 2
Вот как это делает Prototype:
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
};
называется, например:
var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };
var shortnames = Object.extend(arr1,arr2);
EDIT: добавлен hasOwnProperty(), как указано в bucabay в комментариях
Ответ 3
Теперь, в 2016 году, я бы сказал, что лучший/стандартный способ - Object.assign()
Чистый Javascript. Нет jQuery.
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2); // Object {a: 4, b: 2, c: 110}
Дополнительная информация, примеры и polyfill здесь:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Ответ 4
Держите его простым...
function mergeArray(array1,array2) {
for(item in array1) {
array2[item] = array1[item];
}
return array2;
}
Ответ 5
Underscore также имеет метод расширения:
Скопировать все свойства исходных объектов в объект назначения. Он в порядке, поэтому последний источник будет отменять свойства с тем же именем в предыдущих аргументах.
_.extend(destination, *sources)
_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
Ответ 6
В dojo слияние двух объектов/массивов будет lang.mixin(destination, source)
- вы также можете смешивать несколько источников в один пункт назначения и т.д. - подробнее см. ссылку на функцию mixin.
Ответ 7
Вы хотите переписать свойство, если имена совпадают, но значения не являются?
И хотите ли вы навсегда изменить один из исходных объектов,
или вы хотите вернуть новый объединенный объект?
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];
}
}
}
}
Ответ 8
Перемещение вашей собственной функции расширения/микширования
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???' });
...
Это просто расширяет знак объектов, рекурсивно. Также обратите внимание, что эта рекурсивная функция TCO (Tail-Call Optimized), поскольку ее возврат является последним вызовом для себя.
Кроме того, вам могут потребоваться целевые свойства. В этом случае вы можете захотеть сконденсировать объекты на основе id
, quantity
или другого свойства. Этот подход может иметь небольшую книгу, написанную об этом, и требует объектно-сопоставления и может стать очень сложным. Я написал небольшую библиотеку для этого, которая доступна по запросу.
Надеюсь, это поможет!
Ответ 9
- В Javascript нет понятия ассоциативный массив, есть объекты
- Единственный способ объединить два объекта: для их свойств и указатели копий к их значениям, которые не являются примитивными типами и значениями для примитивных типов для другого Экземпляр
Ответ 10
У UI (YUI) Yahoo также есть вспомогательная функция для этого:
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);
Ответ 11
Мне нужно слияние с глубокими объектами. Поэтому все остальные ответы мне не очень помогли. _.extend и jQuery.extend преуспевают, если у вас нет рекурсивного массива, как я. Но это не так уж плохо, вы можете запрограммировать его через пять минут:
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;
}
Ответ 12
jquery имеет логическое значение для глубокой копии. Вы можете сделать что-то вроде этого:
MergeRecursive = function(arr1, arr2){
$.extend(true, arr1, arr2);
return arr1;
};
Также вы можете отредактировать эту функцию для поддержки n-массивов для объединения.
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;
};
Итак, теперь вы можете сделать
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);
Ответ 13
Объединить массивы в jQuery, что относительно $.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';
Ответ 14
Рекурсивное решение (расширяет также массивы объектов) + null checked
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;
};
Испытания
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 }
Ответ 15
Вот лучшее решение.
obj1.unshift.apply( obj1, obj2 );
Кроме того, obj1
может вырасти внутри цикла без каких-либо проблем. (скажем, obj2
является динамическим)