Reputation: 20722
I'm looking for a concise way of creating an object whose property names match values from an array, where all properties have the same value (e.g. true
). As an example:
My ID array looks like these arbitrary (in the actual software, not necessarily unique and not necessarily numeric, but primitive) values:
var ids = [4, 15, 8, 16, 42, 23];
I am looking for some simple call to convert this into the following object:
{ 4: true, 15: true, 8: true, 16: true, 42: true, 23: true }
With JavaScript objects internally being hashmaps, such an object should be much more convenient for quickly checking whether a given ID is contained in the array.
Now, of course I know how to generate this object. It's a four-liner:
var idMap = {};
ids.forEach(function (v) {
idMap[v] = true;
});
As this pattern occurs over and over in my code (lots of different item IDs being handled in this application), I feel the percentage of "boilerplate" in this is still too large. Furthermore, it appears to me that the four-liner occasionally distracts from the actually tricky algorithms for doing something with various of these ID lists. Therefore, I am looking for a shorter way to write this, hoping that there is something built-in either to standard JavaScript or to lodash, which is already in use in our application.
The most related question I could find appears to be lodash: mapping array to object. Yet, its proposed solutions are not really shorter and more legible than the above, basically replacing one sort of boilerplate code with another sort (as in my case, I'd usually throw away what the suggested solutions use as values for the object properties and always use true
or some similarly small truthy value).
Is there something built-in that allows for a very simple command like
var idMap = arrayToMap(ids);
or
var idMap = arrayToMap(ids, true);
whose actual name I have not yet found?
(Obviously, the fallback solution is to simply write such a function in our application. I'd prefer to stick as closely as possible with the existing functions, though, hence this question.)
Upvotes: 4
Views: 2392
Reputation: 4175
Well, I think you can easily map the source array to array of pairs, and then construct the object (or even to ES6 Map
) easily.
Just do:
_.fromPairs(ids.map(a=>[a,true]))
and that's it.
Here is an working example:
var ids = [4, 15, 8, 16, 42, 23];
var idsMap = _.fromPairs(ids.map(a=>[a,true])); // however true can be replaced with a variable
console.log(idsMap);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Another way:
_(ids).keyBy(v=>v).mapValues(v=>true).value()
Here is the working example:
var ids = [4, 15, 8, 16, 42, 23];
var idsMap = _(ids).keyBy(v=>v).mapValues(x=>true).value();
console.log(idsMap)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
And, If you are really sure that (consideration) all of your id will be truthy value, then you can take that as an advantage, and just create a map with the same key/value pair, and check for truthiness with any id directly with O(1)
Just Do:
_.keyBy(ids)
And you are done :)
And you don't need the additional .mapValues(v=>true)
from the 2nd solution as you are aware about truthiness of values.
Here is the working snippet:
var ids = [4, 15, 8, 16, 42, 23];
var idsMap = _.keyBy(ids);
console.log(idsMap);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Upvotes: 3
Reputation: 2704
You could add it to the Array.prototype
in your application:
var ids = [4, 15, 8, 16, 42, 23];
Array.prototype.toThing = function(propVal) {
return this.reduce((res, val) => {
res[val] = propVal;
return res;
}, {})
}
console.log(ids.toThing(true));
Upvotes: 1
Reputation: 191976
You can create a simple function that generates maps for you:
var ids = [4, 15, 8, 16, 42, 23];
function hash(arr, prop) {
return arr.reduce(function(r, n) {
r[prop ? n[prop] : n] = true;
return r;
}, {});
}
console.log(hash(ids));
var objs = [{ a: 1 }, { a: 2 }, { a: 3}];
console.log(hash(objs, 'a'));
You can use an ES6 Set:
const ids = [4, 15, 8, 16, 42, 23];
const set = new Set(ids);
console.log(set.has(16));
Upvotes: 1