Reputation: 11781
Say I have something like this:
let values = [1,2,3,4];
let newValues = values.map((v) => {
return v *v ;
});
console.log(newValues); //[1,4,9,16]
Pretty straight forward.
Now what if I want to return multiple values for each of my objects?
eg.
let values = [1,2,3,4];
let newValues = values.map((v) => {
return [v *v, v*v*v, v+1] ;
});
console.log(newValues); //This is what I want to get
//[1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5]
I can use a reduce function
let values = [1,2,3,4];
let newValues = values.map((v) => {
return [v *v, v*v*v,v+1] ;
}).reduce((a, c) => {
return a.concat(c);
});
console.log(newValues);
But is that the best way to do this?
Upvotes: 81
Views: 99557
Reputation: 191966
If you need to map an array, and flatten the results you can use Array.flatMap()
:
const values = [1,2,3,4];
const newValues = values.flatMap((v) => [v *v, v*v*v, v+1]);
console.log(JSON.stringify(newValues)); //[1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5]
If Array.flatMap()
is not available flatten the results of the map by using Array#concat and the spread syntax:
const values = [1,2,3,4];
const newValues = [].concat(...values.map((v) => [v *v, v*v*v, v+1]));
console.log(JSON.stringify(newValues)); //[1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5]
Upvotes: 67
Reputation: 6629
With using only one reduce()
you can do this. you don't need map()
.
better approach is this:
const values = [1,2,3,4];
const newValues= values.reduce((acc, cur) => {
return acc.concat([cur*cur , cur*cur*cur, cur+1]);
// or acc.push([cur*cur , cur*cur*cur, cur+1]); return acc;
}, []);
console.log('newValues =', newValues)
EDIT: The better approach is just using a flatMap (as @ori-drori mentioned):
const values = [1,2,3,4];
const newValues = values.flatMap((v) => [v *v, v*v*v, v+1]);
console.log(JSON.stringify(newValues)); //[1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5]
Upvotes: 86
Reputation: 2859
Better use flatMap
from lodash
const output = _.flatMap([1,2,3,4], (v, index, arr) => [v *v, v*v*v, v+1])
output: [ 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5 ]
Upvotes: 0
Reputation: 707218
By definition, .map()
returns an array of the same length as the input array so it's just not a good choice when you want to create a different length result.
From an efficiency point of view, it's probably best to use for/of
and avoid creating lots of intermediate arrays:
let values = [1,2,3,4];
let result = [];
for (let val of values) {
result.push(val*val , val*val*val, val+1);
}
If you wanted to use array methods efficiently, you could use .reduce()
with .push()
to avoid creating a new array on every iteration:
let values = [1,2,3,4];
let result = values.reduce((array, val) => {
array.push(val*val , val*val*val, val+1);
return array;
}, []);
Upvotes: 7