I've an array (example array below) -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
I want to iterate through this array of objects and produce a new Object (not specifically reduce).
I've these two approaches -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
// using Array.prototype.map()
b = a.map(function(item){
var res = {};
res[item.name] = item.value;
return res;
});
console.log(JSON.stringify(b));
var newObj = [];
// using Array.prototype.forEach()
a.forEach(function(d){
var obj = {};
obj[d.name] = d.value;
newObj.push(obj)
});
console.log(JSON.stringify(newObj))
I've an array (example array below) -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
I want to iterate through this array of objects and produce a new Object (not specifically reduce).
I've these two approaches -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
// using Array.prototype.map()
b = a.map(function(item){
var res = {};
res[item.name] = item.value;
return res;
});
console.log(JSON.stringify(b));
var newObj = [];
// using Array.prototype.forEach()
a.forEach(function(d){
var obj = {};
obj[d.name] = d.value;
newObj.push(obj)
});
console.log(JSON.stringify(newObj))
Is it not right to just use either one for this sort of operations? Also, I'd like to understand the use case scenarios where one will be preferred over the other? Or should I just stick to for-loop?
Share Improve this question edited May 5, 2015 at 11:52 Yellen asked Apr 28, 2015 at 18:35 YellenYellen 1,80016 silver badges35 bronze badges 7- map() can let you avoid the closure and hard-coded var name that forEach() requires to get output. – dandavis Commented Apr 28, 2015 at 18:37
- @dandavis - But somewhere, we do need to use the returned value from map() as well. How much overhead will one variable have? – Yellen Commented Apr 28, 2015 at 18:39
- 2 if you don't need a return, use forEach(), which without a return, runs about 10-20% faster than map(). the advantage of map isn't speed, it's re-usability; you can use the same generic processing function in many places with map(), whereas with forEach, you'd need to define the function next to the output-collecting closure to have it work correctly. – dandavis Commented Apr 28, 2015 at 18:41
-
@dandavis, this is not really true. Based off the tests that I've run,
map
is actually faster thanforEach()
for @Seram's case. – boombox Commented Apr 28, 2015 at 19:40 - 1 @boombox: i said "without a return" forEach is faster. as in, if you fed the forEach callback of the OP to [].map instead. forEach() does less work given the same inputs as map(). since the op does need output, it's an impure use of forEach(), and that impurity prevents not only re-usability but low-level optimizations as well, so it runs slower. in short, pure functions without closure are the fastest way "functional" to collect output, and you need map() to run those. incidentally, _.map() does less work than [].map, and approaches loop speed, if perf is a concern. – dandavis Commented Apr 28, 2015 at 20:05
2 Answers
Reset to default 8 +50As you've already discussed in the ments, there's no outright wrong answer here. Aside from some rather fine points of performance, this is a style question. The problem you are solving can be solved with a for
loop, .forEach()
, .reduce()
, or .map()
.
I list them in that order deliberately, because each one of them could be re-implemented using anything earlier in the list. You can use .reduce()
to duplicate .map()
, for instance, but not the reverse.
In your particular case, unless micro-optimizations are vital to your domain, I'd make the decision on the basis of readability and code-maintenance. On that basis, .map()
does specifically and precisely what you're after; someone reading your code will see it and know you're consuming an array to produce another array. You could acplish that with .forEach()
or .reduce()
, but because those are capable of being used for more things, someone has to take that extra moment to understand what you ARE using them for. .map()
is the call that's most expressive of your intent.
(Yes, that means in essence prioritizing efficiency-of-understanding over efficiency-of-execution. If the code isn't part of a performance bottleneck in a high-demand application, I think that's appropriate.)
You asked about scenarios where another might be preferred. In this case, .map()
works because you're outputting an array, and your output array has the same length as your input array. (Again; that's what .map()
does). If you wanted to output an array, but you might need to produce two (or zero) elements of output for a single element of input, .map()
would be out and I'd probably use .reduce()
. (Chaining .filter().map()
would also be a possibility for the 'skip some input elements' case, and would be pretty legible)
If you wanted to split the contents of the input array into multiple output arrays, you could do that with .reduce()
(by encapsulating all of them as properties of a single object), but .forEach()
or the for
loop would look more natural to me.
First, either of those will work and with your example there's no reason not to use which ever is more fortable for your development cycle. I would probably use map
since that is what is for; to create "a new array with the results of calling a provided function on every element in this array."
However, are you asking which is the absolute fastest? Then neither of those; the fastest by 2.5-3x will be a simple for-loop (see http://jsperf./loop-vs-map-vs-foreach for a simple parison):
var newObj = [];
for (var i = 0, item; item = a[i]; i++) {
var obj = {};
obj[item.name] = item.value;
newObj.push(obj);
});
console.log(JSON.stringify(newObj));