I have an array of many unique strings and I'd like, without looping if at all possible, to create a map object from it where the key for each element is a unique string and the value is defaulted to some arbitrary setting.
Is there a way I can do this in one line without looping? I.e. I want to go from
var colours = [ "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" ];
to
var colourMap = {
"Red": VAL,
"Orange": VAL,
"Yellow": VAL,
"Green": VAL,
"Blue": VAL,
"Indigo": VAL,
"Violet": VAL
};
I have an array of many unique strings and I'd like, without looping if at all possible, to create a map object from it where the key for each element is a unique string and the value is defaulted to some arbitrary setting.
Is there a way I can do this in one line without looping? I.e. I want to go from
var colours = [ "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" ];
to
var colourMap = {
"Red": VAL,
"Orange": VAL,
"Yellow": VAL,
"Green": VAL,
"Blue": VAL,
"Indigo": VAL,
"Violet": VAL
};
Share
Improve this question
asked Feb 3, 2014 at 15:13
Component 10Component 10
10.5k7 gold badges52 silver badges68 bronze badges
8
- You mention in a ment below that you are looking to optimize this for performance since this code will be code repeatedly. First of all, can't you cache this in a variable in a higher scope? Unless the color list or VAL is going to be different every time there is no reason why you cannot. Second - are you sure performance is a problem? Most of the different techniques (for loop, reduce, forEach, underscore) have very similar performance and are unlikely to be your bottleneck. Profile before micro-optimizing! – George Mauer Commented Feb 3, 2014 at 15:39
- @GeorgeMauer: Yes, good points which I will follow up. I suppose my underlying interest here was whether there is a way of doing this that is not O(n) - It sounds like there isn't. – Component 10 Commented Feb 3, 2014 at 15:46
- JS hardly ever neatly follows those ptime predictions you learned in CS. depending on your needs, Object.create() could be a lot faster. – dandavis Commented Feb 3, 2014 at 15:47
- I don't think its even theoretically possible for any operations on each element of an unordered array to be less than O(n). However, isn't O(n) the exact case that most algorithms try to get to? Once you're O(n) you're basically in "not a problem" territory. – George Mauer Commented Feb 3, 2014 at 15:49
- sure it is, do some repetitive benchmarks in V8 or TraceMonkey and you'll see what i mean. if the routine is piled and not runtime optimized, the old rules apply. – dandavis Commented Feb 3, 2014 at 15:50
3 Answers
Reset to default 5Assuming your browser requirements support Array.prototype.reduce
colours.reduce(function(obj, c){
obj[c] = "VAL";
return obj;
}, {})
or if you're ok with being a jerk and using syntax most js devs aren't even aware exists
colours.reduce(function(obj, c){ return (obj[c] = "VAL", obj) }, {})
If you really want to skip loops altogether (Including functions like map
), this works:
JSON.parse('{"'+colours.join('":"VAL", "')+'":"VAL"}');
This builds a JSON string, then parses it.
However, I wouldn't use this function. It's ugly, inefficient, hard to maintain, uses loops "under the hood", and it's generally bad form. (I'm not even gonna bother with eval
instead of JSON. eval === evil
).
Go for something like map
instead:
var colours = [ "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" ];
var colourMap = {};
colours.forEach(function(c){
colourMap[c] = "VAL";
});
Yes, it's looping through the colours
, but it's more efficient, and easier to understand.
Regarding performance:
map
and reduce
seem to be similar in execution speed (reduce
is slightly faster), in Google Chrome.
You can do it with jQuery:
colourMap = $.map(colours, function(e){
return { e: "VAL" };
});
or with Underscore:
var colourMap = {};
_.each(some_object_array, function(val) {
colourMap[val] = "VAL";
});
Or even better (Thanks to George Mauer):
_.object(_.map(colourMap, function(c) { return [c, "VAL"] }))