Преобразование массива в объект

каков наилучший способ преобразования:

['a','b','c']

в:

{
  0: 'a',
  1: 'b',
  2: 'c'
}

30 ответов


ECMAScript 6 вводит легко polyfillable Object.assign:

на Object.assign() метод используется для копирования значений всех перечисляемые собственные свойства от одного или нескольких объектов-источников до цели объект. Он вернет целевой объект.

Object.assign({}, ['a','b','c']); // {0:"a", 1:"b", 2:"c"}

собственные length свойство массива не копируется, потому что оно не перечисляется.


С такой функцией:

function toObject(arr) {
  var rv = {};
  for (var i = 0; i < arr.length; ++i)
    rv[i] = arr[i];
  return rv;
}

Ваш массив уже является более или менее просто объектом, но массивы имеют некоторое "интересное" и специальное поведение по отношению к целочисленным именованным свойствам. Вышеизложенное даст вам простой объект.

редактировать о, Также вы можете захотеть учесть "отверстия"в массиве:

function toObject(arr) {
  var rv = {};
  for (var i = 0; i < arr.length; ++i)
    if (arr[i] !== undefined) rv[i] = arr[i];
  return rv;
}

в современных средах выполнения JavaScript вы можете использовать .reduce() способ:

var obj = arr.reduce(function(acc, cur, i) {
  acc[i] = cur;
  return acc;
}, {});

, что также позволяет избежать "дырки" в массиве, потому что это как .reduce() строительство.


вы можете использовать аккумулятор aka reduce.

['a','b','c'].reduce(function(result, item, index, array) {
  result[index] = item; //a, b, c
  return result;
}, {}) //watch out the empty {}, which is passed as "result"

передать пустой объект {} в качестве отправной точки; затем" увеличьте " этот объект постепенно. В конце итераций,result будет {"0": "a", "1": "b", "2": "c"}

если Ваш массив представляет собой набор объектов пары ключ-значение:

[{ a: 1},{ b: 2},{ c: 3}].reduce(function(result, item) {
  var key = Object.keys(item)[0]; //first property: a, b, c
  result[key] = item[key];
  return result;
}, {});

будет: {a: 1, b: 2, c: 3}

для полноты, reduceRight позволяет перебирать массив в обратном порядке порядок:

[{ a: 1},{ b: 2},{ c: 3}].reduceRight(/* same implementation as above */)

будет: {c:3, b:2, a:1}

ваш аккумулятор может быть любого типа для определенной цели. Например, чтобы поменять ключ и значение вашего объекта в массиве, pass []:

[{ a: 1},{ b: 2},{ c: 3}].reduce(function(result, item, index) {
  var key = Object.keys(item)[0]; //first property: a, b, c
  var value = item[key];
  var obj = {};
  obj[value] = key;
  result.push(obj);
  return result;
}, []); //an empty array

будет: [{1: "a"}, {2: "b"}, {3: "c"}]

в отличие от map, reduce не может использоваться в качестве сопоставления 1-1. Вы имеете полный контроль над элементами, которые вы хотите включить или исключить. Поэтому reduce позволяет достичь чего filter тут, что делает reduce очень разносторонний:

[{ a: 1},{ b: 2},{ c: 3}].reduce(function(result, item, index) {
  if(index !== 0) { //skip the first item
    result.push(item);
  }
  return result;
}, []); //an empty array

будет: [{2: "b"}, {3: "c"}]

осторожностью: reduce и Object.key часть ECMA 5th edition; вы должны предоставить polyfill для браузеров, которые их не поддерживают (особенно IE8).

см. реализацию по умолчанию Mozilla.


Если вы используете jquery:

$.extend({}, ['a', 'b', 'c']);

для полноты, распространение ECMAScript 2015(ES6). Потребуется либо транспилер (Babel), либо среда, работающая по крайней мере ES6.

{ ...['a', 'b', 'c'] }

Я бы, вероятно, написал это так (так как очень редко у меня не будет библиотеки underscorejs под рукой):

var _ = require('underscore');

var a = [ 'a', 'b', 'c' ];
var obj = _.extend({}, a);
console.log(obj);
// prints { '0': 'a', '1': 'b', '2': 'c' }

вот метод O (1) ES2015 только для полноты.

var arr = [1, 2, 3, 4, 5]; // array, already an object
Object.setPrototypeOf(arr, Object.prototype); // now no longer an array, still an object

удивлен, что не вижу -

Object.assign({}, your_array)

Object.assign({}, ['one', 'two']); // {0: 'one', 1: 'two'}

простой способ в современном JavaScript-использовать Object.assign() это не делает ничего, кроме копирования key: value из одного объекта в другой. В нашем случае, Array дарит свойства new {}.


Я закончил использование оператора распространения объектов, так как он является частью стандарта ECMAScript 2015 (ES6).

const array = ['a', 'b', 'c'];
console.log({...array});
// it outputs {0:'a', 1:'b', 2:'c'}

сделал следующее скрипка в качестве примера.


можно использовать Object.assign и array.reduce функция преобразования массива в объект.

var arr = [{a:{b:1}},{c:{d:2}}] 
var newObj = arr.reduce((a, b) => Object.assign(a, b), {})

console.log(newObj)

пять лет спустя, есть хороший способ :)

Object.assign был представлен в ECMAScript 2015.

Object.assign({}, ['a', 'b', 'c'])
// {'0':'a', '1':'b', '2':'c'}

вы можете использовать spread operator

x = [1,2,3,10]
{...x} // {0:1, 1:2, 2:3, 3:10}

быстрый и грязный:

var obj = {},
  arr = ['a','b','c'],
  l = arr.length; 

while( l && (obj[--l] = arr.pop() ) ){};

начиная с Lodash 3.0.0 вы можете использовать _.toPlainObject

var obj = _.toPlainObject(['a', 'b', 'c']);
console.log(obj);
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>

Если вы используете ES6, вы можете использовать Object.назначение и операторов

{ ...['a', 'b', 'c'] }

Если у вас есть вложенный массив как

var arr=[[1,2,3,4]]
Object.assign(...arr.map(d => ({[d[0]]: d[1]})))

быстрый и грязный #2:

var i = 0
  , s = {}
  , a = ['A', 'B', 'C'];

while( a[i] ) { s[i] = a[i++] };

Я бы сделал это просто с Array.of(). массив имеет возможность использовать его контекст в качестве конструктора.

примечание 2 функция является намеренно общим заводским методом; это не требует, чтобы это значение было конструктором массива. Поэтому он может быть передан или унаследован другими конструкторами это может быть вызвано одним числовым аргументом.

так мы можем связать Array.of() функции и генерировать массив как объект.

function dummy(){};
var thingy = Array.of.apply(dummy,[1,2,3,4]);
console.log(thingy);

С помощью Array.of() можно даже сделать подкласс массива.


вот решение в coffeescript

arrayToObj = (arr) ->
  obj = {}
  for v,i in arr
    obj[i] = v if v?
  obj

Это позволяет генерировать из массива объект с ключами, которые вы определяете в нужном вам порядке.

Array.prototype.toObject = function(keys){
    var obj = {};
    var tmp = this; // we want the original array intact.
    if(keys.length == this.length){
        var c = this.length-1;
        while( c>=0 ){
            obj[ keys[ c ] ] = tmp[c];
            c--;
        }
    }
    return obj;
};

result = ["cheese","paint",14,8].toObject([0,"onion",4,99]);

console.log(">>> :" + result.onion); выведет "paint", функция должна иметь массивы равной длины или вы получите пустой объект.

вот обновленный метод

Array.prototype.toObject = function(keys){
    var obj = {};
    if( keys.length == this.length)
        while( keys.length )
            obj[ keys.pop() ] = this[ keys.length ];
    return obj;
};

вот рекурсивная функция, которую я только что написал. Это просто и хорошо работает.

// Convert array to object
var convArrToObj = function(array){
    var thisEleObj = new Object();
    if(typeof array == "object"){
        for(var i in array){
            var thisEle = convArrToObj(array[i]);
            thisEleObj[i] = thisEle;
        }
    }else {
        thisEleObj = array;
    }
    return thisEleObj;
}

вот пример (jsFiddle):

var array = new Array();
array.a = 123;
array.b = 234;
array.c = 345;
var array2 = new Array();
array2.a = 321;
array2.b = 432;
array2.c = 543;
var array3 = new Array();
array3.a = 132;
array3.b = 243;
array3.c = 354;
var array4 = new Array();
array4.a = 312;
array4.b = 423;
array4.c = 534;
var array5 = new Array();
array5.a = 112;
array5.b = 223;
array5.c = 334;

array.d = array2;
array4.d = array5;
array3.d = array4;
array.e = array3;


console.log(array);

// Convert array to object
var convArrToObj = function(array){
    var thisEleObj = new Object();
    if(typeof array == "object"){
        for(var i in array){
            var thisEle = convArrToObj(array[i]);
            thisEleObj[i] = thisEle;
        }
    }else {
        thisEleObj = array;
    }
    return thisEleObj;
}
console.log(convArrToObj(array));

результаты: Recursive Array to Object


Если вы используете angularjs, вы можете использовать angular.расширьте, тот же эффект с $.продлить в jQuery.

var newObj = {};
angular.extend(newObj, ['a','b','c']);

.reduce((o,v,i)=>(o[i]=v,o), {})

[docs]

или более многословным

var trAr2Obj = function (arr) {return arr.reduce((o,v,i)=>(o[i]=v,o), {});}

или

var transposeAr2Obj = arr=>arr.reduce((o,v,i)=>(o[i]=v,o), {})

самый короткий с ванилью JS

JSON.stringify([["a", "X"], ["b", "Y"]].reduce((o,v,i)=>{return o[i]=v,o}, {}))
=> "{"0":["a","X"],"1":["b","Y"]}"

более сложный пример

[["a", "X"], ["b", "Y"]].reduce((o,v,i)=>{return o[v[0]]=v.slice(1)[0],o}, {})
=> Object {a: "X", b: "Y"}

еще короче (с помощью function(e) {console.log(e); return e;} ===(e)=>(console.log(e),e))

 nodejs
> [[1, 2, 3], [3,4,5]].reduce((o,v,i)=>(o[v[0]]=v.slice(1),o), {})
{ '1': [ 2, 3 ], '3': [ 4, 5 ] }

[/docs]


если вы можете использовать Map или Object.assign, это очень легко.

создать массив:

const languages = ['css', 'javascript', 'php', 'html'];

ниже создается объект с индексом в качестве ключей:

Object.assign({}, languages)

повторить то же самое с картами

преобразуется в объект на основе индекса {0 : 'css'} etc...

const indexMap = new Map(languages.map((name, i) => [i, name] ));
indexMap.get(1) // javascript

преобразовать в объект на основе значения {css : 'css is great'} etc...

const valueMap = new Map(languages.map(name => [name, `${name} is great!`] ));
valueMap.get('css') // css is great

используя javascript, вы можете сделать это forEach

var result = {},
    attributes = ['a', 'b','c'];

attributes.forEach(function(prop,index) {
  result[index] = prop;
});

С ECMA6:

attributes.forEach((prop,index)=>result[index] = prop);

С помощью синтаксис ES6 в вы можете сделать что-то вроде:

const arr = ['a', 'b', 'c'];
const obj = {...arr}; // -> {0: "a", 1: "b", 2: "c"} 

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

var toObject = function(array) {
    var o = {};
    for (var property in array) {
        if (String(property >>> 0) == property && property >>> 0 != 0xffffffff) {
            o[i] = array[i];
        }
    }
    return o;
};

этот должен обрабатывать разреженные массивы более эффективно.


это не имеет прямого отношения, но я пришел сюда в поисках одной строки для объединения вложенных объектов, таких как

const nodes = {
    node1: {
        interfaces: {if1: {}, if2: {}}
    },
    node2: {
        interfaces: {if3: {}, if4: {}}
    },
    node3: {
        interfaces: {if5: {}, if6: {}}
    },
}

решение заключается в использовании комбинации reduce и object spread:

const allInterfaces = nodes => Object.keys(nodes).reduce((res, key) => ({...res, ...nodes[key].interfaces}), {})

let i = 0;
let myArray = ["first", "second", "third", "fourth"];

const arrayToObject = (arr) =>
    Object.assign({}, ...arr.map(item => ({[i++]: item})));

console.log(arrayToObject(myArray));

или использовать

myArray = ["first", "second", "third", "fourth"]
console.log({...myArray})

Я сталкивался с этой проблемой несколько раз и решил написать функцию, которая является как можно более общей. Посмотрите и не стесняйтесь изменять что-нибудь

function typeOf(obj) {
    if ( typeof(obj) == 'object' ) {
        if (obj.length)
            return 'array';
        else
            return 'object';
    } else
    return typeof(obj);
}

function objToArray(obj, ignoreKeys) {
    var arr = [];
    if (typeOf(obj) == 'object') {
        for (var key in obj) {
            if (typeOf(obj[key]) == 'object') {
                if (ignoreKeys)
                    arr.push(objToArray(obj[key],ignoreKeys));
                else
                    arr.push([key,objToArray(obj[key])]);
            }
            else
                arr.push(obj[key]);
        }
    }else if (typeOf(obj) == 'array') {
        for (var key=0;key<obj.length;key++) {
            if (typeOf(obj[key]) == 'object')
                arr.push(objToArray(obj[key]));
            else
                arr.push(obj[key]);
        }
    }
    return arr;
}