815

What is the best way to convert:

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

to:

{
  0: 'a',
  1: 'b',
  2: 'c'
}
leonheess
  • 16,068
  • 14
  • 77
  • 112
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • 2
    If anyone else is looking for a Lodash solution, consider `_.keyBy` (formerly `_.indexBy`): https://lodash.com/docs#keyBy – 2540625 Feb 18 '16 at 02:26
  • 1
    This is a bit confusing because arrays are objects already, but I guess the point of the question is converting the [array](http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects) [exotic object](http://www.ecma-international.org/ecma-262/6.0/#sec-exotic-object) to an [ordinary object](http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object). – Oriol Apr 03 '16 at 17:25
  • 3
    A simple way to do this with Lodash is `_.toPlainObject`. Ex: `var myObj = _.toPlainObject(myArr)` – julian soro Nov 04 '16 at 19:36

46 Answers46

989

ECMAScript 6 introduces the easily polyfillable Object.assign:

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

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

The own length property of the array is not copied because it isn't enumerable.

Also, you can use ES8 spread syntax on objects to achieve the same result:

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

For custom keys you can use reduce:

['a', 'b', 'c'].reduce((a, v) => ({ ...a, [v]: v}), {}) 
// { a: "a", b: "b", c: "c" }
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • 4
    Just want to point out - if you already have an array of sorted properties from the original object, using the **spread** operator is what will turn that array directly into a new object: `{ ...[sortedArray]}` – HappyHands31 Jul 26 '19 at 15:18
  • 22
    Oriol, is there a way to set a fixed key instead of 0 & 1? – Menai Ala Eddine - Aladdin Apr 24 '20 at 00:00
  • 5
    This is usually not what you want. Usually you want to use a property in the array element as a key. Thus, the reduce is what you want. – Thomas Beauvais Oct 05 '20 at 10:28
  • why mvc does not allow to us to post array. Why we must convert array to object? –  Mar 03 '21 at 11:43
  • 2
    what if i want the key not as 0,1,2 but the same as the value? like: {a: 'a'} How do we do that ? – Gel Jun 11 '21 at 13:03
  • 9
    @Gel Use `reduce` like: `arr.reduce((a, v) => ({ ...a, [v]: v}), {})` – David Hellsing Sep 13 '21 at 09:28
  • This is just what I was looking for, I can do: `{...arr}` and done – alextrastero Jun 16 '22 at 08:12
  • how can I reduce a large flat array of objects to one object, like `[{a:'b'},{c:'d'},,{}...]` to `{a:'b',c:'d',..}`. [Here](https://stackoverflow.com/a/20909965/1705829) it is – Timo Jul 22 '22 at 15:11
  • [See](https://stackoverflow.com/a/46928438/1705829) `reduce` and `Object.assign` together: `var newObj = arr.reduce((a, b) => Object.assign(a, b), {})` – Timo Jul 22 '22 at 17:02
  • What about doing the reverse? ie from { 0: 'a', 1: 'b, 3: 'd' } to [ 'a', 'b', , 'd' ] - kind of like Object.values() except ensuring the order and 'holes'... – Max Waterman Oct 12 '22 at 10:28
556

With a function like this:

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

Your array already is more-or-less just an object, but arrays do have some "interesting" and special behavior with respect to integer-named properties. The above will give you a plain object.

edit oh also you might want to account for "holes" in the array:

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

In modern JavaScript runtimes, you can use the .reduce() method:

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

That one also avoids "holes" in the array, because that's how .reduce() works.

Jordan Frankfurt
  • 334
  • 1
  • 3
  • 13
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • thought this was great just added a few things for my own enjoyment returns an object you can't reference outside function so just showed example of that and adding something to the object property names `x = ['a','b','c'] var b = {} function toObject(arr) { var rv = {}; for (var i = 0; i < arr.length; ++i) if (arr[i] !== undefined) { rv['key_' + i] = arr[i]; } b = rv return b; } toObject(x) b.key_0` – James Daly Sep 12 '12 at 04:29
  • What about `var arr = []; arr['foo'] = "bar"`? Can this be converted to object? – m93a May 11 '13 at 09:04
  • 2
    @m93a it already is an object. In JavaScript, there's really no point creating an Array instance (`[]`) if you're not going to use numeric property keys and the "length" property. – Pointy May 11 '13 at 13:16
  • @Pointy Nope, it's not an usual object - try converting to JSON, it treats really werid. – m93a May 11 '13 at 20:20
  • 1
    @m93a All array instances are objects. Properties with string (non-numeric) names like "foo" are merely properties of that object, and as such they're just like properties of any other object. The properties with numeric names (like "12" or "1002") are special in that the runtime system automatically adjusts the "length" property accordingly when values are assigned. Also, `.push()`, `.pop()`, `.slice()`, etc. all only work on numeric properties, and not properties like "foo". – Pointy May 12 '13 at 01:42
  • @Pointy Try to run this in your JS console: `var a = ["x", "y"]; a["foo"] = "z"; b = {1:"x",2:"y","foo":"z"}; console.log(JSON.stringify(a)); console.log(JSON.stringify(b));`. – m93a May 13 '13 at 14:36
  • @m93a the `JSON.stringify` code can tell the difference between a real Array instance and an object with numeric keys. When it sees a real array, all that it serializes is the "real" list of properties that comprise the numerically-indexed array. I have never noticed that behavior, but it's yet another good reason not to use an Array when you really just want an Object. – Pointy May 13 '13 at 14:59
  • @Pointy, what are your one- and two-letter variables supposed to indicate? – 2540625 Sep 03 '14 at 23:29
  • @janaspage well "i" is just a numeric index into the numbered properties of the array, and "rv" is the return value of that function. – Pointy Sep 04 '14 at 00:21
  • 22
    cleaner way to avoid param reassign `const obj = arr.reduce((obj, cur, i) => { return { ...obj, [i]: cur }; }, {});` – huygn Jan 09 '17 at 08:42
  • If you had an array of objects and you would like to transform that array in a n object you could do: `const optionPriceArray = [ {option: 'economy', price:200}, {option: 'tourist', price:100} ]; ` and then: `const newObj = optionPriceArray.reduce(function(acc, cur) { acc[cur.option] = cur.price; return acc; }, {});` which outputs: `//newObj = {'economy': 200, 'tourist': 100}` – Watchmaker Dec 19 '17 at 19:11
  • 1
    @huygn will your approach be not more expensive in terms of number of lines that it has to process.Since everytime instead of using the same object, you are creating a new one by spreading the params which to es5 would be a for loop iterating over the properties.It seems that this might just make the function slow.What do you think? – VivekN Mar 05 '18 at 20:19
  • 6
    Arrow + destructuring syntax w/o explicit return: `const obj = arr.reduce((obj, cur, i) => ({ ...obj, [i]: cur }), {});` – Marc Scheib Mar 27 '18 at 08:23
  • 2
    As @VivekN said, is it necessary to create new object every time? What about `arr.reduce((obj, cur, i) => (obj[i]=cur,obj), {});` ? – miro Jun 06 '18 at 09:03
  • 3
    @eugene_sunic indeed, but that approach was not available when I answered this in 2010 :) – Pointy Jul 14 '18 at 15:22
  • 2
    As @miro points out, creating a new object every time is not necessary, and in fact _much slower_ than manipulating the initial object that was created. Running a JSPerf test on an array of 1000 elements, creating a new object every time is **1,000** times slower than mutating the existing object. https://jsperf.com/array-prototype-reduce-mutate-vs-intermediate-objects – romellem Nov 26 '19 at 17:00
362

You could use an accumulator 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"

Pass an empty object {} as a starting point; then "augment" that object incrementally. At the end of the iterations, result will be {"0": "a", "1": "b", "2": "c"}

If your array is a set of key-value pair objects:

[{ 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;
}, {});

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

For the sake of completeness, reduceRight allows you to iterate over your array in reverse order:

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

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

Your accumulator can be of any type for you specific purpose. For example in order to swap the key and value of your object in an array, 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

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

Unlike map, reduce may not be used as a 1-1 mapping. You have full control over the items you want to include or exclude. Therefore reduce allows you to achieve what filter does, which makes reduce very versatile:

[{ 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

will produce: [{2: "b"}, {3: "c"}]

Caution: reduce and Object.key are part of ECMA 5th edition; you should provide a polyfill for browsers that don't support them (notably IE8).

See a default implementation by Mozilla.

roland
  • 7,695
  • 6
  • 46
  • 61
  • 2
    Helpful with maintaining a redux store when you are using a map of objects and you need to drop one of the keys – dhruvpatel Jul 05 '19 at 22:27
106

If you're using jquery:

$.extend({}, ['a', 'b', 'c']);
Max
  • 11,377
  • 5
  • 24
  • 15
  • 4
    Weird, if I give in an Array variable it puts every character in a separate object: 0: "a", 1: ",", 2: "b"... So it ignores the quotes, but includes the commas... – TrySpace Jun 20 '12 at 11:22
  • @Max I think there is no such behavior. The returned object is `{0: 'a', 1: 'b', 2: 'c'}` what is an expected result. – ivkremer Nov 13 '13 at 21:07
  • 3
    Is there a way to use $.extend while also informing the keys in a non-numerical manner, ie: making calcultations on the array items? – Davi Lima Nov 13 '14 at 00:21
75

For completeness, ECMAScript 2015(ES6) spreading. Will require either a transpiler(Babel) or an environment running at least ES6.

console.log(
   { ...['a', 'b', 'c'] }
)
vsync
  • 118,978
  • 58
  • 307
  • 400
mcmhav
  • 973
  • 8
  • 9
59

In case you want to use one of the properties of the iterated objects as key, for example:

// from:
const arr = [
    {
        sid: 123,
        name: 'aaa'
    },
    {
        sid: 456,
        name: 'bbb'
    },
    {
        sid: 789,
        name: 'ccc'
    }
];
// to:
{
  '123': { sid: 123, name: 'aaa' },
  '456': { sid: 456, name: 'bbb' },
  '789': { sid: 789, name: 'ccc' }
}

Use:

const result = arr.reduce((obj, cur) => ({...obj, [cur.sid]: cur}), {})
Johnathan Kanarek
  • 834
  • 1
  • 10
  • 16
48

I'd probably write it this way (since very rarely I'll not be having the underscorejs library at hand):

var _ = require('underscore');

var a = [ 'a', 'b', 'c' ];
var obj = _.extend({}, a);
console.log(obj);
// prints { '0': 'a', '1': 'b', '2': 'c' }
Prerna Jain
  • 1,240
  • 2
  • 16
  • 34
Dave Dopson
  • 41,600
  • 19
  • 95
  • 85
  • 9
    you downvote my response, but no comment? My answer is correct and tested. What is the objection? – Dave Dopson Jun 13 '12 at 00:33
  • 16
    This question has no underscore tag, and you are also assuming node.js or a require library. – David Hellsing Nov 04 '12 at 09:45
  • 11
    underscore is pretty common on both client and server. It's assumed for Backbone.js and is probably THE most common utility library. That being said, I included the require line to make it clear I was using a library. There's no 1-liner for describing "add underscore.js to your page", so some translation is required for a browser environment – Dave Dopson Nov 05 '12 at 06:19
  • 6
    Still, if you’re using undserscore, a simple `obj=_.extend({},a);` would do the job. Also, if you are iterating through arrays I’d say `_.each` would be more appropriate than `_.map`. All in all, this is not a good answer on several levels. – David Hellsing Nov 05 '12 at 13:04
  • 1
    Your suggestion to use _.extend is a good one. I didn't realize that would work on an array. Normally I prefer 'map' to 'each' because perf micro-optimization aside, 'map' can accomplish everything that 'each' accomplishes, reducing by 1 the number of methods I need to think about.... that's one of my few complaints about underscore, having too many methods where a smaller canonical set would suffice. JS1.6 seems to agree with me, defining a built in 'map', but no 'each' method. – Dave Dopson Nov 05 '12 at 18:52
  • 1
    Using underscore and Backbone and this solved my problem perfectly. Thanks. – Aaron Miler Mar 02 '13 at 03:44
  • 3
    @CharlieMartin that analogy is completely flawed, because lodash, underscore, and jQuery are not "standard libraries" and, in a great number of JavaScript use cases, adding libraries directly impacts end users, which one should not do for trivial reasons. – morewry Mar 30 '17 at 22:47
  • 1
    @morewry I was trying to suggest that they should be in the standard libraries in javascript. Not that they are. `_.extend` was added to the standard libraries in ECMA 6 as `Object.assign` anyway – Charlie Martin Apr 03 '17 at 00:05
41

Not many people here commented of Object.fromEntries, I really enjoy it, since it's cleaner and works easily with TypeScript, without bothering too much about generic types and stuff. It also allows custom keys with map, if needed. Cons: you'll need an additional map, if you want a custom key. E.g.:

const tags = [
  { name: 'AgeGroup', value: ageGroup },
  { name: 'ApparelTypes', value: apparelTypes },
  { name: 'Brand', value: brand },
  // ...
]

const objectTags = Object.fromEntries(tags.map((t) => [t.name, t.value]))

/*
{
  AgeGroup: 'Adult',
  Apparel: 'Creeper, Jacket'
  Brand: '',
  // ...
}
*/
giovannipds
  • 2,860
  • 2
  • 31
  • 39
30

we can use Object.assign and array.reduce function to convert an Array to Object.

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

console.log(newObj)
KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133
  • 1
    This is what I was looking for. I didn't need the indeces, I needed to transform the array into retained key-value pairs. – Mike K Feb 18 '20 at 12:46
  • plus one for the KungFu, I need it for conversion of `arr = [{ b: 1, d: 2 }]` to obj. – Timo Jul 22 '22 at 16:45
27

Here is an O(1) ES2015 method just for completeness.

var arr = [1, 2, 3, 4, 5]; // array, already an object
Object.setPrototypeOf(arr, Object.prototype); // now no longer an array, still an object
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • (1) According to [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf), changing the [[Prototype]] of an object is a very slow operation. (2) This does not remove the own `length` property. (3) The object is still an array, `Array.isArray(arr) === true`. (4) Special array behaviors are not removed, e.g. `arr.length = 0` removes all indices. (5) [Therefore, I think `Object.assign` is much better](http://stackoverflow.com/a/36388401/1529630). – Oriol Apr 03 '16 at 17:11
  • 1
    @Oriol mdn is wrong, at least in V8 (but also other engines) this is a pretty fast operation in this particular case - since objects have a numerical store anyway this is basically changing two pointers. – Benjamin Gruenbaum Jun 24 '16 at 10:17
  • This also can be used for the fact that it is apparently unique among the other quick solutions, of preserving any non-index ("own") properties on the array (i.e., non-positive-integer properties)... – Brett Zamir Nov 27 '18 at 08:55
  • But hmm, `Array.isArray` is returning `true` for the "object" here even though `instanceof Array` does not... – Brett Zamir Nov 27 '18 at 08:59
  • @BrettZamir that sounds like a bug :D – Benjamin Gruenbaum Nov 27 '18 at 10:44
18

FWIW, one another recent approach is to use the new Object.fromEntries along with Object.entries as follows:

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

...which allows for avoiding storing sparse array items as undefined or null and preserves non-index (e.g., non-positive-integer/non-numeric) keys.

{ 0: "a", 1: "b", 2: "c", "-2": "d", hello: "e" }

(Same result here as with @Paul Draper's Object.assign answer.)

One may wish to add arr.length, however, as that is not included:

obj.length = arr.length;
Brett Zamir
  • 14,034
  • 6
  • 54
  • 77
15

Using javascript#forEach one can do this

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

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

With ECMA6:

attributes.forEach((prop,index)=>result[index] = prop);
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53
13

If your array contains 2-element arrays where first element is the key and second element is the value you can easily convert to object using reduce.

[
  ["key1","value1"], 
  ["key2", "value2"], 
  ["key3", "value3"]
]
.reduce((acc, [key, value])=>({...acc, [key]: value}), {});

Result:

{  
  key1: 'value1',   
  key2: 'value2', 
  key3: 'value3'  
}  
Marinos An
  • 9,481
  • 6
  • 63
  • 96
10

If you're using ES6, you can use Object.assign and the spread operator

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

If you have nested array like

var arr=[[1,2,3,4]]
Object.assign(...arr.map(d => ({[d[0]]: d[1]})))
murthy naika k
  • 559
  • 6
  • 12
  • 1
    Not only are your variable names different, but your example will not work, creating a map from the constructor initially requires 2d key-value Array. `new Map([['key1', 'value1'], ['key2', 'value2']]);` – Shannon Hochkins May 17 '17 at 03:38
6

Quick and dirty #2:

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

while( i < a.length ) { s[i] = a[i++] };
lordkrandel
  • 185
  • 2
  • 8
6

A quick and dirty one:

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

while( l && (obj[--l] = arr.pop() ) ){};
Mic
  • 24,812
  • 9
  • 57
  • 70
6

More browser supported and more flexible way of doing that is using a normal loop, something like:

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

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

But also the modern way could be using the spread operator, like:

{...arr}

Or Object assign:

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

Both will return:

{0: "a", 1: "b", 2: "c"}
Alireza
  • 100,211
  • 27
  • 269
  • 172
5

A simple and cheeky method of quickly converting an Array of items in to an Object

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

Then using it like so...

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

Output:

pork pie

Checking the type:

typeof obj
"object"

AND things wouldn't be complete if there wasn't a prototype method

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

Using like:

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

Output:

cheese whizz

*NOTE that there is no naming routine, so if you want to have specific names, then you will need to continue using the existing methods below.


Older method

This allows you to generate from an array an object with keys you define in the order you want them.

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); will output "paint", the function has to have arrays of equal length or you get an empty object.

Here is an updated method

Array.prototype.toObject = function(keys){
    var obj = {};
    if( keys.length == this.length)
        while( keys.length )
            obj[ keys.pop() ] = this[ keys.length ];
    return obj;
};
Mark Giblin
  • 1,086
  • 2
  • 13
  • 20
  • This destroys both the keys array content and, despite the internal comment, also the values array (its contents). JavaScript works differently than PHP with JavaScript automatically acting by reference on the properties of an object/array. – Brett Zamir Feb 03 '14 at 12:01
  • No it doesn't, the routine makes copies, the original is not touched. – Mark Giblin Feb 08 '14 at 23:29
  • Yes, the original is touched. See http://jsfiddle.net/bRTv7/ . The array lengths end up both being 0. – Brett Zamir Feb 08 '14 at 23:37
  • Ok, the edited version I just changed it with does not destroy the arrays, find that strange that it should have done that. – Mark Giblin Feb 10 '14 at 23:19
  • `var tmp = this;` had just made a reference, not a copy, as with the keys array you had passed into the function. As mentioned, JavaScript works differently than PHP. I also fixed your current function's while loop condition to be `>=0` instead of `>0` because otherwise you would avoid including the first item in the array (at the 0 index). – Brett Zamir Feb 10 '14 at 23:43
  • See http://jsfiddle.net/WpM3h/ for your latest version before my modification: http://jsfiddle.net/WpM3h/ – Brett Zamir Feb 10 '14 at 23:46
  • 1
    Updated method that should be supported in older browsers as JSON has been around longer than ECMA added new code features – Mark Giblin Jan 30 '20 at 14:43
4
.reduce((o,v,i)=>(o[i]=v,o), {})

[docs]

or more verbose

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

or

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

shortest one with vanilla JS

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

some more complex example

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

even shorter (by using 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]

test30
  • 3,496
  • 34
  • 26
4

As of Lodash 3.0.0 you can use _.toPlainObject

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

If you can use Map or Object.assign, it's very easy.

Create an array:

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

The below creates an object with index as keys:

Object.assign({}, languages)

Replicate the same as above with Maps

Converts to an index based object {0 : 'css'} etc...

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

Convert to an value based object {css : 'css is great'} etc...

const valueMap = new Map(languages.map(name => [name, `${name} is great!`] ));
valueMap.get('css') // css is great
Shannon Hochkins
  • 11,763
  • 15
  • 62
  • 95
4

Why No One try this? in ES6

let arr = ['a','b','c']
let {...obj} = arr
console.log(obj) //  {0: 'a', 1: 'b', 2: 'c'}
let {...obj2} = ['a','b','c']
console.log(obj2) //  {0: 'a', 1: 'b', 2: 'c'}

is Very simple way?

j-shan huang
  • 102
  • 1
  • 3
  • 9
    Rather than just criticizing other answers for not trying something, you can explain what advantages your answer has or how it differs from the top answer using "spread syntax". Hint: See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#rest_property. – General Grievance Sep 06 '22 at 12:50
  • how to make keys is value ? – Yogi Arif Widodo Nov 17 '22 at 10:48
4

The shortest answer: (using destructuring)

const obj = { ...input }

Example:

const inputArray = ["a", "b", "c"]
const outputObj = { ...inputArray }
Bryan Enid
  • 414
  • 3
  • 12
3

Here's a recursive function I just wrote. It's simple and works well.

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

Here's an example (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));

Results: Recursive Array to Object

JVE999
  • 3,327
  • 10
  • 54
  • 89
3

I would do this simply with Array.of(). Array of has the ability to use it's context as a constructor.

NOTE 2 The of function is an intentionally generic factory method; it does not require that its this value be the Array constructor. Therefore it can be transferred to or inherited by other constructors that may be called with a single numeric argument.

So we may bind Array.of() to a function and generate an array like object.

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

By utilizing Array.of() one can even do array sub-classing.

Community
  • 1
  • 1
Redu
  • 25,060
  • 6
  • 56
  • 76
3

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

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

console.log(arrayToObject(myArray));

Or use

myArray = ["first", "second", "third", "fourth"]
console.log({...myArray})
Mahdi Bashirpour
  • 17,147
  • 12
  • 117
  • 144
3

ES5 - Solution:

Using Array prototype function 'push' and 'apply' you can populate the object with the array elements.

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
SridharKritha
  • 8,481
  • 2
  • 52
  • 43
3

Try using reflect to copy from array item to object.

var arr =['aa:23','bb:44','cc:55']
    var obj ={}
    arr.forEach(e => {
        var ee = e.split(':')
        Reflect.set(obj,ee[0],ee[1])
    });
    console.log(obj) // { aa: '23', bb: '44', cc: '55' }
3

If someone is searching for a Typescript method, i wrote this:

const arrayToObject = <T extends Record<K, any>, K extends keyof any>(
  array: T[] = [],
  getKey: (item: T) => K,
) =>
  array.reduce((obj, cur) => {
    const key = getKey(cur)
    return ({...obj, [key]: cur})
  }, {} as Record<K, T>)

It will:

  1. enforce first param to be array of objects
  2. help to select the key
  3. enforce the key to be an key of all array items

Example:

// from:
const array = [
    { sid: 123, name: 'aaa', extra: 1 },
    { sid: 456, name: 'bbb' },
    { sid: 789, name: 'ccc' }
];
// to:
{
  '123': { sid: 123, name: 'aaa' },
  '456': { sid: 456, name: 'bbb' },
  '789': { sid: 789, name: 'ccc' }
}

usage:

const obj = arrayToObject(array, item => item.sid) // ok
const obj = arrayToObject(array, item => item.extra) // error

Here's a demo.

isherwood
  • 58,414
  • 16
  • 114
  • 157
Emanuel
  • 2,603
  • 22
  • 24
  • This is nice and easily modified to meet other reqs – Lasf Apr 23 '22 at 23:19
  • Excellent little solution, works like a charm! How to change the output into '123': 'aaa' as per your example? – Mecanik Jul 22 '22 at 02:42
  • Modified function for anyone looking to do what I needed: const arrayToObject = , K extends keyof any>( array: T[] = [], getKey: (item: T) => K, ) => array.reduce((obj, cur) => { const key = getKey(cur) return ({...obj, [key]: Object.entries(cur).reduce((str, [p, val]) => { return `${val}`; }, '') }) }, {} as Record); – Mecanik Jul 22 '22 at 02:53
  • Does not work with Date types. Try adding a new property of type Date, then select it – Cristian E. Nov 01 '22 at 12:58
2

If you like oneliners, and IE8 is not a problem anymore (as it should be)

['a','b','c'].reduce((m,e,i) => Object.assign(m, {[i]: e}), {});

Go ahead and try it on the browser console

It coult be more verbose like this:

['a','b','c'].reduce(function(memo,elm,idx) {
    return Object.assign(memo, {[idx]: elm});
}, {});

But still rules out IE8. If IE8 is a must, then you can use lodash/underscore like that:

_.reduce(['a','b','c'], function(memo,elm,idx) {
    return Object.assign(memo, {[idx]: elm});
}, {})
2

You could use a function like this:

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

This one should handle sparse arrays more efficiently.

Pablo Cabrera
  • 5,749
  • 4
  • 23
  • 28
2

It's not directly relevant but I came here searching for a one liner for merging nested objects such as

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

The solution is to use a combination of reduce and object spread:

const allInterfaces = nodes => Object.keys(nodes).reduce((res, key) => ({...res, ...nodes[key].interfaces}), {})
Adnan Y
  • 2,982
  • 1
  • 26
  • 29
2

Simplest way to do this is the following:

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

function ConvertArr(arr) { 
 if (typeof(arr) === 'array') {
 Object.assign(obj, arr);
}

This way it only runs if it is an array, however, you can run this with let global object variable or without, that's up to you, if you run without let, just do Object.assign({}, arr).

  • This is the same solution as provided in the [top answer](https://stackoverflow.com/a/36388401/1974224) – Cristik Jul 04 '22 at 03:54
2

Use the javascript lodash library. There is a simple method _.mapKeys(object, [iteratee=_.identity]) that can do the conversion.

ascripter
  • 5,665
  • 12
  • 45
  • 68
jude ugwu
  • 59
  • 5
1

Here's a solution in coffeescript

arrayToObj = (arr) ->
  obj = {}
  for v,i in arr
    obj[i] = v if v?
  obj
David
  • 606
  • 6
  • 11
1

If you are using angularjs you can use angular.extend, the same effect with $.extend of jquery.

var newObj = {};
angular.extend(newObj, ['a','b','c']);
Vicruz
  • 321
  • 1
  • 12
1

Below method would convert array to object with particular given key.

    /**
     * Converts array to object
     * @param  {Array} array
     * @param  {string} key (optional)
     */
    Array.prototype.ArrayToObject = function(key) {
       const array = this;
       const obj = {};

       array.forEach((element, index) => {
           if(!key) {
              obj[index] = element;
           } else if ((element && typeof element == 'object' && element[key])) {
              obj[element[key]] = element;
           }
       });
    return obj;
    }

For Ex -

[{name: 'test'}, {name: 'test1'}].ArrayToObject('name');

would give

{test: {name: 'test'}, test1: {name: 'test1'}}

and incase key is not provided as param to the method

i.e. [{name: 'test'}, {name: 'test1'}].ArrayToObject();

would give

{0: {name: 'test'}, 1: {name: 'test1'}}
shubhamkes
  • 516
  • 5
  • 12
0

I would use underscore for this, but if that isn't available then I would drop down to using reduce with an initial value of empty object {}

>>> ['a', 'b', 'c'].reduce(function(p, c, i) {p[i] = c; return p}, {})
Object { 0="a", 1="b", 2="c"}

reduce should be widely available in most browsers today, see MDN

Meitham
  • 9,178
  • 5
  • 34
  • 45
  • The same solution was already provided in the [second top answer](https://stackoverflow.com/a/4215753/1974224). – Cristik Jul 04 '22 at 03:58
  • @Cristik it does now, but it didn’t at the time. It’s one annoying trend now for top answers to copy snippets from bottom answers without providing credit. – Meitham Jul 04 '22 at 07:53
  • I looked at the revision history before posting the comment, and it showed the edit that introduced the `reduce()` was added on Mar 12, 2014, which was before your answer was posted. – Cristik Jul 04 '22 at 07:57
0

It is easy to use javascript reduce:

["a", "b", "c", "d"].reduce(function(previousValue, currentValue, index) { 
   previousValue[index] = currentValue; 
   return previousValue;
}, 
{}
);

You can take a look at Array.prototype.reduce(), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Ping.Goblue
  • 576
  • 8
  • 12
  • The same solution was already provided in the [second top answer](https://stackoverflow.com/a/4215753/1974224). – Cristik Jul 04 '22 at 03:58
0

typescript solutioin:

export const toMap = (errors: ResponseError[]) => {
  const errorMap: Record<string, string> = {};
  errors.forEach(({ field, message }) => {
    errorMap[field] = message;
  });
  return errorMap;
};

export type FieldError = {
  field: string;
  message: string;
};
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
-1

initial array and will convert into an Object with keys which will be the unique element of an array and the keys value will be how many times the perticular keys will be repeating

var jsTechs = ['angular', 'react', 'ember', 'vanilaJS', 'ember', 'angular', 'react', 'ember', 'vanilaJS', 'angular', 'react', 'ember', 'vanilaJS', 'ember', 'angular', 'react', 'ember', 'vanilaJS', 'ember', 'angular', 'react', 'ember', 'vanilaJS', 'ember', 'react', 'react', 'vanilaJS', 'react', 'vanilaJS', 'vanilaJS']

var initialValue = {
  java : 4
}

var reducerFunc = function reducerFunc (initObj, jsLib) {
  if (!initObj[jsLib]) {
    initObj[jsLib] = 1
  } else {
    initObj[jsLib] += 1
  }
  return initObj
}
var finalResult = jsTechs.reduce(reducerFunc, initialValue)
console.log(finalResult)
bvmCoder
  • 1,131
  • 9
  • 8
-1
import books from "./books.json";

export const getAllBooks = () => {
  return {
    data: books,
    // a=accoumulator, b=book (data itelf), i=index
    bookMap: books.reduce((a, book, i) => {
      // since we passed {} as initial data, initially a={}
      // {bookID1:book1, bookID2:i}
      a[book.id] = book;
      // you can add new property index
      a[book.id].index=i
      return a;
      // we are passing initial data structure
    }, {}),
  };
};
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
-1

I have faced this issue multiple times and decided to write a function that is as generic as possible. Have a look and feel free to modify anything

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;
}
  • 1
    Note that your "typeOf" function is notoriously dangerous - some objects just happen to have a "length" property. I'd recommend using the methods in [underscore.js](http://documentcloud.github.com/underscore/#isArray), like "_.isArray(obj)". – Dave Dopson Feb 21 '12 at 18:57
  • 2
    just check for obj instanceof Array instead of checking for length – Johan Aug 17 '12 at 07:24
-2

My version array to json in JS. Jusy copy/paste and use it. Isn't this awesome? I love this type of functions I found on StackOverflow.

function array2json(arr) {
    var parts = [];
    var is_list = (Object.prototype.toString.apply(arr) === '[object Array]');

    for(var key in arr) {
        var value = arr[key];
        if(typeof value == "object") { //Custom handling for arrays
            if(is_list) parts.push(array2json(value)); /* :RECURSION: */
            else parts[key] = array2json(value); /* :RECURSION: */
        } else {
            var str = "";
            if(!is_list) str = '"' + key + '":';

            //Custom handling for multiple data types
            if(typeof value == "number") str += value; //Numbers
            else if(value === false) str += 'false'; //The booleans
            else if(value === true) str += 'true';
            else str += '"' + value + '"'; //All other things
            // :TODO: Is there any more datatype we should be in the lookout for? (Functions?)

            parts.push(str);
        }
    }
    var json = parts.join(",");

    if(is_list) return '[' + json + ']';//Return numerical JSON
    return '{' + json + '}';//Return associative JSON
}
Adrian P.
  • 5,060
  • 2
  • 46
  • 47
-5

var finalResult = ['a','b','c'].map((item , index) => ({[index] : item}));
console.log(finalResult)
  • 3
    the returns an array of objects. the question was about a single object with index as a key and value as the value. – its4zahoor Jun 16 '20 at 11:07
-10

A more OO approach:

Array.prototype.toObject = function() {
 var Obj={};

 for(var i in this) {
  if(typeof this[i] != "function") {
   //Logic here
   Obj[i]=this[i];
  }
 }

 return Obj;
}
  • 17
    There are a couple of problems with this approach, 1; you are extending the native prototype. 2; you are using `for in` in an array wich will also loop through static properties of the array. 3; why are you excluding functions? – David Hellsing Nov 04 '12 at 09:33