How to create an object from an Array of key-value pairs?

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.

Answers:

Answer

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.

Answer

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;

Answer

Lodash's fromPairs function will do this:

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

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.

Answer

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.

Answer

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.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.