2015-06-30 5 views
20

Данный вход:Свести массив с объектами в 1 объект

[{ a: 1 }, { b: 2 }, { c: 3 }] 

Как вернуть:

{ a: 1, b: 2, c: 3 } 

Для массивов it's not a problem с lodash, но здесь мы имеем массив объектов.

+0

Является ли это даже хорошо спросить о SO для пакетов npm? –

+0

№ Вы можете описать возникшую у вас проблему, как вы это делали, и если ответ «установить этот пакет npm», то это нормально; но вы не должны специально запрашивать пакет для решения проблемы. – JJJ

ответ

39

Использование Object.assign:

let merged = Object.assign(...arr); // ES6 (2015) syntax 

var merged = Object.assign.apply(Object, arr); // ES5 syntax 

Обратите внимание, что Object.assign еще не реализована во многих среде, и вы, возможно, потребуется polyfill его (либо с колонкового JS, другой polyfill или с помощью polyfill на MDN).

Вы упомянули lodash, так что стоит отметить, это идет с _.assign функции для этой цели, что делает то же самое:

var merged = _.assign.apply(_, [{ a: 1 }, { b: 2 }, { c: 3 }]); 

Но я действительно рекомендую новый стандартный путь библиотеки.

+3

Очень приятное решение! – nils

+3

Разве вы не делаете 'Object.assign ({}, ... arr)' ?! – Bergi

+0

@Bergi Я могу, если я хочу сохранить вход 'assign' неповрежденным. Мне, конечно, не нужно, если я этого не сделаю. Поскольку это не было требованием, я не рассматривал его как таковой. –

4

Вот версия не использует методы ES6 ...

var arr = [{ a: 1 }, { b: 2 }, { c: 3 }]; 
var obj = {}; 

for(var i = 0; i < arr.length; i++) { 
    var o = arr[i]; 
    for(var key in o) { 
     if(typeof o[key] != 'function'){ 
      obj[key] = o[key]; 
     } 
    } 
} 

console.log(obj); 

скрипку: http://jsfiddle.net/yaw3wbb8/

+2

Обратите внимание, что это также скопирует перечислимые свойства прототипа (что не является проблемой в данном конкретном случае). –

+0

будет простой '&&! O.propertyIsEnumerable (key)', добавленный в инструкцию if, исправить это? –

+0

Ну, для ... только перечисляет перечислимые свойства. Объект Object (o) .hasOwnProperty (obj) 'будет исправлять его (если он не находится на прототипе) - часть' Object (o) 'состоит в том, чтобы гарантировать, что мы не вызываем несуществующий метод, чтобы, например прохождение '4' не подведет (и ничего не копирует). –

3

Вы можете использовать функцию underscore.extend так:

var _ = require('underscore'); 
var a = [{ a: 1 }, { b: 2 }, { c: 3 }]; 

var result = _.extend.apply(null, a); 
console.log(result); // { a: 1, b: 2, c: 3 } 
console.log(a); // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ] 

И для предотвращения изменения исходного массива вы должны использовать

var _ = require('underscore'); 
var a = [{ a: 1 }, { b: 2 }, { c: 3 }]; 

var result = _.extend.apply(null, [{}].concat(a)); 
console.log(result); // { a: 1, b: 2, c: 3 } 
console.log(a); // [ { a: 1 }, { b: 2 }, { c: 3 } ] 

Here can test it

1

У меня аккуратное решения не требующее polyfill.

var arr = [{ a: 1 }, { b: 2 }, { c: 3 }]; 
var object = {}; 

arr.map(function(obj){ 
    var prop = Object.getOwnPropertyNames(obj); 
    object[prop] = obj[prop]; 
}); 

Надежда, что помогает :)

+2

Я понятия не имею, почему это было поддержано, поскольку он не может не работать - getOwnPropertyNames возвращает массив. –

+0

@BenjaminGruenbaum Для этого варианта использования он отлично работает. См. Мою скрипку: http://jsfiddle.net/dhgsbg99/ –

+1

Это просто случайно, поскольку все объекты имеют одно свойство, а 'toString' массив с единственным свойством дает тот же результат, попробуйте добавить свойство к одному из объекты и увидеть это не удается: http://jsfiddle.net/zqvhceyj/ –

4

С lodash, вы можете использовать merge():

var arr = [ { a: 1 }, { b: 2 }, { c: 3 } ]; 
_.merge.apply(null, [{}].concat(arr)); 
// → { a: 1, b: 2, c: 3 } 

Если вы делаете это в нескольких местах, вы можете сделать merge() немного более элегантным путем используя partial() и :

var merge = _.spread(_.partial(_.merge, {})); 
merge(arr); 
// → { a: 1, b: 2, c: 3 } 
Смежные вопросы