703

What is the best way to convert:

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

to:

{
  0: 'a',
  1: 'b',
  2: 'c'
}
isherwood
  • 52,576
  • 15
  • 105
  • 143
David Hellsing
  • 102,045
  • 43
  • 170
  • 208
  • 12
    Its worth pointing out that Javascript arrays *are* objects. – Spudley Nov 18 '10 at 14:32
  • 1
    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

49 Answers49

788

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
  • 102,045
  • 43
  • 170
  • 208
Oriol
  • 249,902
  • 55
  • 405
  • 483
544

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
  • 324
  • 1
  • 4
  • 12
Pointy
  • 389,373
  • 58
  • 564
  • 602
  • 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
339

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,395
  • 6
  • 45
  • 60
  • 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,008
  • 5
  • 23
  • 15
72

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
  • 103,437
  • 51
  • 275
  • 359
mcmhav
  • 943
  • 8
  • 9
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,180
  • 2
  • 15
  • 32
Dave Dopson
  • 39,848
  • 19
  • 88
  • 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
  • 15
    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
  • 4
    The "you must answer without mentioning underscore or lo-dash" people are so annoying. Comparable to saying that you must answer C++ questions without mentioning the standard libraries. If underscore or lo-dash is not an option, the OP should mention that. – Charlie Martin Dec 04 '14 at 00:28
  • 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
42

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
  • 666
  • 1
  • 8
  • 15
41

Surprised not to see -

console.log(
  Object.assign({}, ['a', 'b', 'c'])
)
mplungjan
  • 155,085
  • 27
  • 166
  • 222
Wylliam Judd
  • 8,295
  • 2
  • 24
  • 35
  • Any smart suggestion to create `{ "first":"a", "second":"b","third":"c" }` with the keys being fixed - I am looking for a destruct – mplungjan Jun 04 '20 at 08:16
  • @mplungjan I would suggest using reduce instead of assign in that case. There is probably a library that would allow you to enumerate over every ordinal if that's needed. – Wylliam Judd Jun 04 '20 at 19:21
  • I had another case today. I ended up asking a question about it: https://stackoverflow.com/questions/62197270/destruct-using-titles/62197439 – mplungjan Jun 04 '20 at 19:31
28

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
  • 260,410
  • 85
  • 489
  • 489
  • (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
28

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
  • 14,686
  • 4
  • 102
  • 112
  • 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
21

I ended up using object spread operator, since it is part of the ECMAScript 2015 (ES6) standard.

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

Made the following fiddle as an example.

locropulenton
  • 4,305
  • 2
  • 30
  • 55
  • 1
    I'm not sure about the performance of this, but out of so many Array to Object conversion (since i want to use objects for all my codes to standardise it), this is probably the easiest. – Someone Special Apr 28 '18 at 10:27
  • How is this better than any of the already existing answers that gave the very same solution? – Dan Dascalescu Apr 03 '19 at 22:54
20

For ES2016, spread operator for objects. Note: This is after ES6 and so transpiler will need to be adjusted.

const arr = ['a', 'b', 'c'];
const obj = {...arr}; // -> {0: "a", 1: "b", 2: "c"} 
dman
  • 11,194
  • 18
  • 93
  • 187
Oleksii Trekhleb
  • 2,263
  • 17
  • 21
18
Object.assign({}, ['one', 'two']); // {0: 'one', 1: 'two'}

Easy way in modern JavaScript is to use Object.assign() that does nothing but copying key:value from one object to another. In our case, Array donates properties to new {}.

Paul Rooney
  • 19,499
  • 9
  • 39
  • 60
Appeiron
  • 1,053
  • 7
  • 14
  • How is this better than any of the already existing answers that gave the very same solution? – Dan Dascalescu Apr 03 '19 at 22:54
  • Dan Dascalescu at time I've added answer there was only above answer regarding `O.assign` but it lacked explanation. Nowadays destructuring array into object is a way (`{...array}`) – Appeiron Apr 04 '19 at 14:25
17

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
  • 13,309
  • 6
  • 48
  • 73
14

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
  • 14,597
  • 5
  • 30
  • 52
12

Five years later, there's a good way :)

Object.assign was introduced in ECMAScript 2015.

Object.assign({}, ['a', 'b', 'c'])
// {'0':'a', '1':'b', '2':'c'}
Paul Draper
  • 71,663
  • 43
  • 186
  • 262
11

you can use spread operator

x = [1,2,3,10]
{...x} // {0:1, 1:2, 2:3, 3:10}
noel zubin
  • 642
  • 9
  • 11
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
  • 529
  • 5
  • 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
9

The simplest way is to use a spread operator.

var arr = ["One", "Two", 3];
var obj = {...arr};
console.log(obj);
Sanan Ali
  • 1,170
  • 1
  • 13
  • 19
6

Quick and dirty #2:

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

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

A quick and dirty one:

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

while( l && (obj[--l] = arr.pop() ) ){};
Mic
  • 24,186
  • 9
  • 56
  • 69
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,008
  • 2
  • 13
  • 19
  • 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
5

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
  • 93,149
  • 25
  • 259
  • 162
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,196
  • 31
  • 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,726
  • 1
  • 17
  • 30
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
  • 10,888
  • 14
  • 56
  • 90
4

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
  • 52,576
  • 15
  • 105
  • 143
Emanuel
  • 1,656
  • 15
  • 20
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,068
  • 9
  • 48
  • 87
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
  • 22,595
  • 5
  • 50
  • 67
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
  • 13,853
  • 11
  • 101
  • 132
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
  • 6,617
  • 2
  • 39
  • 38
3

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

ascripter
  • 4,856
  • 12
  • 44
  • 59
jude ugwu
  • 61
  • 5
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' }
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,654
  • 4
  • 22
  • 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,564
  • 1
  • 23
  • 28
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).

1

Here's a solution in coffeescript

arrayToObj = (arr) ->
  obj = {}
  for v,i in arr
    obj[i] = v if v?
  obj
David
  • 557
  • 4
  • 9
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
  • 476
  • 5
  • 12
1

maybe if you want array value to be your object key too

function toObject(arr) {
  var rv = {};
  for (var i = 0; i < arr.length; ++i)
    rv[arr[i]] = arr[i];
  return rv;
}
Mohammad Reza Mrg
  • 1,045
  • 10
  • 23
1

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
  • 1
  • 7
  • 79
  • 120
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
  • 8,311
  • 4
  • 32
  • 43
0

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});
}, {})
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
  • 516
  • 7
  • 10
0

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,123
  • 9
  • 8
0

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

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.
  • 4,840
  • 1
  • 43
  • 44
-4

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
-8

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