81

In Python one can pass the dict1 constructor a sequence of key-value pairs:

>>> dict([['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']])
{'age': 42, 'name': 'Bob', 'breakfast': 'eggs'}

I can't think of any way to do this sort of thing in JavaScript other than defining my own function for the purpose:

function pairs_to_object(pairs) {
    var ret = {};
    pairs.forEach(function (p) { ret[p[0]] = p[1]; });
    return ret;
}

But I'm a JS noob... Is there anything built-in for this sort pairs-to-object conversion?

1 For the purposes of this question, I'm treating Python dicts as Python's counterpart of JS objects, although, of course the similarity is limited only to the fact that they are both key-value collections.

4
  • "Is there anything built-in for this sort pairs-to-object conversion?" Not in plain JavaScript. Commented Nov 18, 2013 at 23:17
  • 1
    Some libraries offer it: underscorejs.org/#object Commented Nov 18, 2013 at 23:18
  • 4
    There is an ES proposal to add this to JS as Object.fromEntries. Commented Jul 24, 2018 at 20:02
  • This is the inverse of the Object.entries function which was added to JS in ES2017. Commented Jul 24, 2018 at 20:04

8 Answers 8

106

Object.fromEntries does the job. It was added to the language with EcmaScript2019.

If you don't have support for that function, you could define it yourself with the following ES2015 code:

Object.fromEntries = arr => Object.assign({}, ...Array.from(arr, ([k, v]) => ({[k]: v}) ));

A nice thing is that this method does the opposite of Object.entries (ES2017), so now you can go back and forth between the object and array representation:

const arr = [['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']];
const obj = Object.fromEntries(arr);
console.log(obj);
// ... and back:
const arr2 = Object.entries(obj);
console.log(arr2); // copy of the original array (omitting duplicate keys)
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6 Map

There is an alternative to plain objects for key/value pairs: Map.

Its constructor accepts the array-of-pairs format:

// Demo:
const arr = [['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']];

const mp = new Map(arr);

// Get one particular value:
console.log(mp.get('age'));
// Get all the keys:
console.log(...mp.keys());
// Get all the values:
console.log(...mp.values());
// Get all the key/value pairs:
console.log(...mp.entries());

If you really need a plain object, then this is not useful, but a Map might present a viable alternative.

Sign up to request clarification or add additional context in comments.

9 Comments

Unfortunately Map requires extra work if you want to serialize it to JSON. Otherwise your solution is cool! +1
Thanks @Kostanos. Fortunately, the main (Object.assign) part of my answer can be used for generating JSON ;-) Maps have other qualities (like the handy constructor, keeping insertion order, allowing non-strings as keys, providing a size property, ...) that might be interesting in certain use cases.
This is great! Thanks! I'm confused a little bit about how/why the square brackets are used for the key (i.e., {[k]: v}). Is it a destructuring thing? I've been banging my head trying to figure out how to use a variable as a key in this kinda way and when I saw that this worked, I was confused but happy nonetheless.
I'll go ahead and answer it myself... nope, not exactly... Anyone curious can check this article out: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . The pertinent bit is: "Starting with ECMAScript 2015, the object initializer syntax also supports computed property names. That allows you to put an expression in brackets [], that will be computed and used as the property name." I love ES20xx so much...
In the 2018 ES drafts, one can use object spread syntax instead of Object.assign, as follows: <array>.reduce((o, [k, v]) => ({...o, [k]: v}), {}).
|
53

You can use the reduce function

x = [[1,2],[3,4],[5,6]];
o = x.reduce(function(prev,curr){prev[curr[0]]=curr[1];return prev;},{})

o is now the equivalent of {1:2, 3:4, 5:6}

If your input array is sparse, you'll want to add a if(curr!=undefined) test on the assignment, but make sure you still return "prev".

If your tuples are something more complex than simple [key,value], you can simply change the way "prev" is assigned to. Eg: prev["key-"+curr[0].toString()]=curr[1]*2;

1 Comment

This is the best answer since it works in all browsers, and is very compact. Everyone should learn map, filter and reduce. It took me a while to locate the trailing {}, which provides the initial value for reduce. Also, fat arrow syntax would make it even more readable, but wouldn't work in all browsers.
23

At the time of writing (2013) JavaScript objects / dictionaries / associative arrays don't have such a constructor natively.

As you said yourself, you can of course build your own function using for instance a functional approach using the reduce function as explained in one of the other answers. A classic for or newer forEach loop would also work, of course. But there isn't anything built-in.


Edit: It's 2019 and now we have Object.fromEntries, which will give you what you need.

Comments

13

Lodash's fromPairs function will do this:

const _ = require('lodash')
const kvPairs = [['a', 1], ['b', 2]]
_.fromPairs(kvPairs)
// => { a: 1, b: 2 }

Comments

9

Object.fromEntries()

There is a method on the Object object called Object.fromEntries(iterable). The iterator object from the iterable object has to produce an array with 2 elements. The first (index 0) array element will be the object key and the second the value.

MDN describes this very accurately:

The Object.fromEntries() method takes a list of key-value pairs and returns a new object whose properties are given by those entries. The iterable argument is expected to be an object that implements an @@iterator method, that returns an iterator object, that produces a two element array-like object, whose first element is a value that will be used as a property key, and whose second element is the value to associate with that property key.


How to use:

You don't even need to know the specifics of an iterable object in order to use the Object.fromEntries() method. You can always use the method on the following objects:

  • 2 Dimensional arrays where the inner/nested arrays have 2 elements
  • Maps

Here is an example:

// map example:
const map = new Map([ ['hi', 'there'], ['foo', 2] ]);
const objFromMap = Object.fromEntries(map);
console.log(objFromMap); // { hi: "there", foo: 2 }

// array example:
const array = [ ['0', '00'], ['1', '11'], ['2', '22'] ];
const objFromArray = Object.fromEntries(array);
console.log(objFromArray); // { 0: "00", 1: "11", 2: "22" }

Caveat, browser compatibility!

At the time of this writing (december 2019) this method is relatively new and not implemented by all browsers. In order to use this method and to ensure that you JS code will run in all browsers you might have to transpile your code to a earlier version of JS.

1 Comment

like this but lets give it some time :)
0

Javascript does not have a native function for converting an array into an object in the way you have described. But, this is because there is no need for it. You have already included in the question an example solution, where you define the function yourself, but that really isn't necessary. As long as you can be sure that the input array is correct, you could even do the conversion with a simple for loop, like so:

var input = [['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']];
var output = {};
for(i in input) output[input[i][0]] = input[i][1];

Which is just about the most basic code imaginable.

Of course, (as mamapitufo points out) it is generally a bad idea to actually use for..in to iterate over an array, because that will also return non-indexes as values of i. Still, the point is that this kind of operation is too simple, and too rarely needed, to justify having a native function.

The python dict is a structure which is not needed in javascript, because the two languages have different approaches to typing, and to design in general, and so what is useful to one is not useful to another. While you could work on using the same methods and structures that you used in python, it might be a better idea to think about how to take advantage of javascript's different way of doing things - maybe you will find that you don't need a dict after all.

4 Comments

there is an Array.prototype.forEach in ES5: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Using 'for .. in' to iterate over elements in an array in JavaScript is not recommended: stackoverflow.com/a/500531/421089
@mamapitufo You are entirely correct, thanks, and I have edited the answer to clarify what I am trying to say.
> The python dict is a structure which is not needed in javascript Really? So, currently I have a list of key-value pairs. I have a <select>, where the value of each <option> in the <select> is the key, and the value is used for the data of the <option>. I'd like to quickly be able to look up the data in my key-value assoicated with the <option> value. There's no way to do that besides iterating over an array?
@Lucretiel The way to do this in javascript is usually to use an object, as arrays in javascript are very limited, and cannot be associative. Javascript doesn't need an explicit dictionary class, because all objects ARE dictionaries, natively. They can also be classes, functions, and primitives, sometimes all at the same time - which I grant can be quite confusing, but is pretty amazingly flexible once you figure it out.
0
function arrayToObj(ar) {
    var obj={};
    for(let val of ar) {
        obj[val[0]]=val[1];
    }
    return obj; 
}

arrayToObj([['name', 'Bob'], ['age', 42], ['breakfast', 'eggs']]);

Output will be: { name: 'Bob', age: 42, breakfast: 'eggs' }

Comments

-1
const sampleArr = ['foo', 'bar', 'baz', 42];
const _chunk = (arr, chunkSize, chunks = []) => {
  while (arr.length) {
    chunks = [...chunks, arr.splice(0, chunkSize)];
  }
  return chunks;
}; //splice array to chunks

const arr = _chunk(sampleArr, 2);
const entries = new Map([...arr]);

const obj = Object.fromEntries(entries);

console.log(obj)

// expected output: Object { foo: "bar", baz: 42 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.