Перетворити масив в об’єкт


514

Який найкращий спосіб конвертувати:

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

до:

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

3
Можливо, йому потрібно якийсь код набору качок, щоб не думати, що це екземпляр Array
Pointy

6
Варто зазначити, що масиви Javascript - це об'єкти.
Спудлі

Якщо хтось шукає рішення Лодаша, розгляньте _.keyBy(раніше _.indexBy): lodash.com/docs#keyBy
2540625

Це трохи заплутано, оскільки масиви вже є об'єктами, але я думаю, що питання полягає в перетворенні екзотичного масиву масиву в звичайний об'єкт .
Оріол

1
Простий спосіб зробити це з Лодашем _.toPlainObject. Напр .:var myObj = _.toPlainObject(myArr)
Джуліан Соро

Відповіді:


473

ECMAScript 6 представляє легкозахисні матеріали Object.assign:

Object.assign()Метод використовується для копіювання значення всіх перелічуваних власних властивостей з одного або декількох об'єктів джерела до цільового об'єкту. Він поверне цільовий об’єкт.

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

Власне lengthвластивість масиву не копіюється, оскільки воно не перелічується.

Крім того, ви можете використовувати синтаксис поширення ES6 для досягнення того ж результату:

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

Відразу хочу відзначити, - якщо у вас вже є масив відсортованих властивостей від вихідного об'єкта, використовуючи поширення оператора є те , що перетворить цей масив безпосередньо в новий об'єкт:{ ...[sortedArray]}
HappyHands31

Оріоле, чи є спосіб встановити фіксовану клавішу замість 0 і 1?
Менай Ала Еддін

488

З такою функцією:

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()працює.


2
@ m93a це вже об’єкт. У JavaScript насправді немає сенсу створювати екземпляр Array ( []), якщо ви не збираєтесь використовувати цифрові ключі властивості та властивість "length".
Pointy

14
чистіший спосіб уникнути переназначення парамconst obj = arr.reduce((obj, cur, i) => { return { ...obj, [i]: cur }; }, {});
хуйнь

3
Стрілка + деструктуючий синтаксис без явного повернення:const obj = arr.reduce((obj, cur, i) => ({ ...obj, [i]: cur }), {});
Марк Шейб

2
@eugene_sunic насправді, але такий підхід був недоступний, коли я відповів на це у 2010 році :)
Pointy

2
Як зазначає @miro, створювати новий об'єкт щоразу не потрібно, а насправді набагато повільніше, ніж маніпулювати початковим об’єктом, який був створений. Запуск тесту JSPerf на масиві з 1000 елементів, щоразу створюючи новий об’єкт, в 1000 разів повільніше, ніж мутація існуючого об'єкта. jsperf.com/…
romellem

281

Ви можете використовувати акумулятор ака 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}

Ваш акумулятор може бути будь-якого типу для конкретних цілей. Наприклад, для того, щоб поміняти ключ і значення вашого об'єкта в масиві, передайте []:

[{ 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; ви повинні надати полізаповнення для браузерів, які не підтримують їх (особливо IE8).

Дивіться реалізацію Mozilla за замовчуванням .


1
Корисно для підтримки магазину скорочення, коли ви використовуєте карту об’єктів і вам потрібно скинути один з ключів
dhruvpatel

101

Якщо ви використовуєте jquery:

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

4
Дивно, якщо я даю змінну Array, вона ставить кожного символу в окремий об'єкт: 0: "a", 1: ",", 2: "b" ... Отже, він ігнорує лапки, але включає коми .. .
TrySpace

@Max Я думаю, що такої поведінки немає. Повертається об'єкт {0: 'a', 1: 'b', 2: 'c'}- це очікуваний результат.
ivkremer

3
Чи існує спосіб використання $ .extend, а також інформування ключів нечисловим способом, тобто: внесення обчислень на елементи масиву?
Даві Ліма

супер дивовижний і короткий тест
Faisal Mehmood Awan

63

Для повноти розповсюдження ECMAScript 2015 (ES6). Знадобиться або транспілятор (Babel), або середовище, що працює принаймні ES6.

console.log(
   { ...['a', 'b', 'c'] }
)


2
Насправді це також не доступно в ES2015. Однак це дуже елегантно.
Алуан Хаддад

47

Я, мабуть, написав би це так (оскільки дуже рідко я не матиму під рукою бібліотеку підкреслення):

var _ = require('underscore');

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

9
Ви спростуєте мою відповідь, але жодного коментаря? Моя відповідь правильна і перевірена. Яке заперечення?
Дейв Допсон

14
У цьому питанні немає тегу підкреслення, і ви також припускаєте, що node.js або потрібна бібліотека.
Девід Гелсінг

10
Підкреслення досить поширене як для клієнта, так і для сервера. Це передбачається для Backbone.js і, мабуть, ТОБІ найпоширеніша бібліотека утиліт. Коли це було сказано, я включив рядок вимагання, щоб зрозуміти, що я використовую бібліотеку. Немає 1-лайнера для опису "додати underscore.js на свою сторінку", тому для середовища браузера потрібен певний переклад
Дейв Допсон

6
Тим не менш, якщо ви використовуєте несексуальні, простий obj=_.extend({},a);зробив би цю роботу. Крім того, якщо ви повторюєте масиви, я б сказав, що це _.eachбуло б більш доцільно, ніж _.map. Загалом, це не є гарною відповіддю на декількох рівнях.
Девід Гелсінг

4
"Ви повинні відповісти, не згадуючи підкреслення або ломання", так дратують людей. Порівняно з тим, що ви повинні відповідати на питання C ++, не згадуючи стандартних бібліотек. Якщо підкреслення або підкреслення не є варіантом, ОП повинен згадати про це.
Чарлі Мартін

26

Ось метод 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

(1) Згідно з MDN , зміна [[прототипу]] об'єкта - це дуже повільна операція. (2) Це не вилучає власну lengthвласність. (3) Об'єкт по - , як і раніше є масивом, Array.isArray(arr) === true. (4) Спеціальна поведінка масиву не видаляється, наприклад, arr.length = 0видаляє всі індекси. (5) Тому я думаю, що Object.assignце набагато краще .
Оріол

1
@Oriol mdn помиляється, принаймні, у V8 (але також і інших двигунах) це досить швидка операція в даному конкретному випадку - оскільки об'єкти в будь-якому випадку мають числовий запас, це в основному змінює два покажчики.
Бенджамін Груенбаум

Це також може бути використане для того, що воно, очевидно, унікальне серед інших швидких рішень, збереження будь-яких неіндексних ("власних") властивостей масиву (тобто, непозитивних цілих властивостей) ...
Бретт Замір

Але хм, Array.isArrayповертається trueза «об’єктом» сюди, хоча й instanceof Arrayне ...
Бретт Замір

@BrettZamir, що звучить як помилка: D
Бенджамін Груенбаум

26

Здивований, що не бачив -

console.log(
  Object.assign({}, ['a', 'b', 'c'])
)


Будь-яка розумна пропозиція створити { "first":"a", "second":"b","third":"c" }за допомогою фіксованих ключів - я шукаю руйнування
mplungjan

@mplungjan Я б запропонував використовувати у цьому випадку зменшення замість призначення. Напевно, існує бібліотека, яка дозволила б перерахувати кожен порядковий номер, якщо це потрібно.
Вілліям Джадд

У мене сьогодні був інший випадок. Я закінчив тим , як поставити запитання про це: stackoverflow.com/questions/62197270/destruct-using-titles / ...
mplungjan

23

ми можемо використовувати 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)


Це те, що я шукав. Мені не потрібні індекси, мені потрібно було перетворити масив у збережені пари ключ-значення.
Майк К

18

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

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

Наведемо наступну загадку як приклад.


1
Я не впевнений у ефективності цього, але з такої кількості перетворень Array в Object (оскільки я хочу використовувати об'єкти для всіх своїх кодів для його стандартизації), це, мабуть, найпростіше.
Хтось спеціальний

Чим це краще, ніж будь-який із вже існуючих відповідей, який дав саме таке рішення?
Дан Даскалеску

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

Простий спосіб у сучасному JavaScript - це використання, Object.assign()яке не робить нічого, крім копіювання ключа: значення з одного об'єкта на інший. У нашому випадку Arrayдарує майно новому {}.


Чим це краще, ніж будь-який із вже існуючих відповідей, який дав саме таке рішення?
Дан Даскалеску

Ден Даскалеску в той час, коли я додав відповідь, відповідь була лише вище, O.assignале пояснення не вистачало. Нині руйнування масиву в об’єкт - це спосіб ( {...array})
Appeiron

13

Для ES2016 оператор розповсюдження об’єктів. Примітка. Це після ES6, тому транспілер потрібно буде відрегулювати.

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


Відповідь оператора розповсюдження вже була на 2 роки раніше .
Дан Даскалеску


10

Використовуючи javascript#forEachодин, можна це зробити

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

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

З ECMA6:

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

10

Іншим останнім підходом FWIW є використання нового Object.fromEntriesпоряд із Object.entriesнаступним:

const arr = ['a','b','c'];
arr[-2] = 'd';
arr.hello = 'e';
arr.length = 17;
const obj = Object.fromEntries(Object.entries(arr));

... що дозволяє уникнути зберігання розрізнених елементів масиву як undefinedабо nullі зберігає неіндексаційні (наприклад, непозитивні цілі / нечислові) ключі.

arr.lengthОднак ви можете додати , оскільки це не включено:

obj.length = arr.length;


9

Якщо ви використовуєте ES6, ви можете використовувати Object.assign та оператор розповсюдження

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

Якщо ви вклали масив типу

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

1
Мало того, що ваші імена змінних відрізняються, але ваш приклад не буде працювати, для створення карти від конструктора спочатку потрібен масив 2d з ключовим значенням. new Map([['key1', 'value1'], ['key2', 'value2']]);
Шеннон Хочкінс

5

Швидкий і брудний:

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

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

Я думаю, ти забув це перевірити; він виробляє {0:"c", 1:"b", 2:"a"}. Ви або хочете unshiftзамість цього, popабо (краще) почати з i=arr.length-1і замість цього.
Фрогз

так .. просто змінив це, але потім він став менш цікавим: /
Міс

Може навіть зробити l = arr.length, і тоді while (l && (obj[--l] = arr.pop())){}(я розумію, це старе, але чому б не спростити його ще більше).
Qix - МОНІКА ПОМИЛИЛА

2
@Qix, Приємне скорочення
Mic

4

Швидкий і брудний №2:

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

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

Чому ви використовуєте позначення комами?
Коннер Руль

3
Особиста перевага, щоб кома вела в наступному рядку. Мені таке позначення простіше читати.
BingeBoy

1
Цикл припиняється, якщо масив містить хибне значення. Ви повинні перевірити i < a.lengthзамість a[i].
Оріол


3

Ось рекурсивна функція, яку я щойно написав. Це просто і працює добре.

// 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));

Результати: Рекурсивний масив до об'єкта


Працює дуже добре. Спасибі
Ханмасла

Це повинно бути вище вгору, якщо у вас є ['a' = '1', 'b' = '2', 'c' = '3']і хочете, як {a: 1, b: 2, c: 3}це працює ідеально.
Ваньцзя

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

[документи]

або більше багатослівного

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]


Що ви мали намір [/docs]? Було б корисніше зробити фрагменти коду виконаними.
Дан Даскалеску

3

Я б це зробив просто з Array.of(). Масив має можливість використовувати його контекст як конструктор.

ПРИМІТКА 2 Функція - це навмисно загальний заводський метод; не потрібно, щоб його це значення було конструктором масиву. Тому він може бути переданий або успадкований іншими конструкторами, які можуть бути викликані одним числовим аргументом.

Тож ми можемо прив’язатись Array.of()до функції та генерувати масив, схожий на об’єкт.

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

Використовуючи Array.of() один, можна навіть зробити підкласифікацію масиву .


3

Якщо ви можете використовувати Mapабо Object.assign, це дуже просто.

Створіть масив:

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

Нижче створюється об’єкт з індексом як ключі:

Object.assign({}, languages)

Повторіть те саме, що вище, як і в Картах

Перетворює на об'єкт на основі індексу {0 : 'css'}тощо ...

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

Перетворити на об'єкт, заснований на цінності {css : 'css is great'}тощо ...

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

3

Простий і зухвалий метод швидкого перетворення масиву елементів у об’єкт

function arrayToObject( srcArray ){
    return  JSON.parse( JSON.stringify( srcArray ) );
}

Потім використовуючи його так ...

var p = [0,2,3,'pork','pie',6];
obj = new arrayToObject( p );
console.log( obj[3], obj[4] )
// expecting `pork pie`

Вихід:

pork pie

Перевірка типу:

typeof obj
"object"

І все не було б завершеним, якби не було методу прототипу

Array.prototype.toObject =function(){
    return  JSON.parse( JSON.stringify( this ) );
}

Використовуючи:

var q = [0,2,3,'cheese','whizz',6];
obj = q.toObject();
console.log( obj[3], obj[4] )
// expecting `cheese whizz`

Вихід:

cheese whizz

* Зверніть увагу, що немає імен імен, тому якщо ви хочете мати конкретні імена, вам потрібно буде продовжувати використовувати існуючі нижче методи.


Старіший метод

Це дозволяє генерувати з масиву об’єкт за допомогою ключів, визначених вами, у порядку, який ви бажаєте.

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); виведе "фарба", функція повинна мати масиви однакової довжини або ви отримаєте порожній об'єкт.

Ось оновлений метод

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

Це знищує і вміст масиву ключів, і, незважаючи на внутрішній коментар, також масив значень (його вміст). JavaScript працює інакше, ніж PHP, і JavaScript автоматично діє за посиланням на властивості об'єкта / масиву.
Бретт Замір

Ні, ні, рутина робить копії, оригінал не торкається.
Марк Гіблін

Так, оригінал торкається. Дивіться jsfiddle.net/bRTv7 . Довжина масиву в кінці обох дорівнює 0.
Бретт Замір

Гаразд, відредагована версія, з якою я її просто змінила, не знищує масиви, вважаю, що це дивно, що вона мала це зробити.
Марк Гіблін

1
Оновлений метод, який слід підтримувати у старих веб-переглядачах, оскільки JSON довше, ніж ECMA додав нові функції коду
Марк Гіблін

2

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})


2

ES5 - Рішення:

За допомогою функції прототипу Array 'push' та 'Apply' ви можете заповнити об'єкт елементами масиву.

var arr = ['a','b','c'];
var obj = new Object();
Array.prototype.push.apply(obj, arr);
console.log(obj);    // { '0': 'a', '1': 'b', '2': 'c', length: 3 }
console.log(obj[2]); // c


Що робити, якщо я хочу перейти на{ name: a, div :b, salary:c}
Prashant Pimpale

2

Більш підтримувана браузер і гнучкіший спосіб робити це за допомогою звичайного циклу , наприклад:

const arr = ['a', 'b', 'c'],
obj = {};

for (let i=0; i<arr.length; i++) {
   obj[i] = arr[i];
}

Але також сучасним способом може бути використання оператора розповсюдження , наприклад:

{...arr}

Або призначити об’єкт :

Object.assign({}, ['a', 'b', 'c']);

Обидва повернуться :

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

1

Ви можете використовувати таку функцію:

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;
};

Цей повинен обробляти рідкісні масиви ефективніше.


1

Ось рішення в coffeescript

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

7
Що таке кофескрипт? Ми говоримо про JS! : D
m93a

2
Це маленька мова, яка збирається в JavaScript :)
Девід,

6
Хмф, він використовує дивні позначення. Мені більше подобається звичайний JS.
m93a

2
@David Ви можете зробити все для циклу в 1 рядку, щоб зробити все це лише 3 рядки. :) Приклад:obj[i] = v for v,i in arr when v?
XåpplI'-I0llwlg'I -
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.