使用ES6中的map()函数返回多个值

73

假设我有这样的一段代码:

let values = [1,2,3,4]; 

let newValues = values.map((v) => {
  return v *v ; 
}); 

console.log(newValues); //[1,4,9,16]

非常直截了当。

现在如果我想为我的对象返回多个值怎么办?

例如:

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]

我可以使用 reduce 函数

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); 

但这是最好的做法吗?


3
你正在寻求使用 flatmap。请参考这个 Stack Overflow 回答 - Ray Toal
6
谢谢,我感觉很多有效的编程都在于掌握正确的术语。 - dwjohnston
1
请问什么是“链表(linked)”数据结构? - vsync
4个回答

78

使用仅一个reduce()即可完成此操作,无需使用map()。 更好的方法是:

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)

编辑: 更好的方法是使用flatMap(正如@ori-drori所提到的):

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]


为什么不直接使用.push()而不是每次循环都创建一个新数组呢?你可以向.push()传递多个值。实际上,你也不需要使用.reduce()。在你只需要向先前声明的数组中.push()值的情况下,for/of.forEach()也能正常工作。 - jfriend00
3
@jfriend00 因为 reduce() 是一种函数式编程方法(我的首选)。当然,你的解决方案也很好。 - Emad Emami
不喜欢是因为(1)这很慢-On^2-,(2)内置函数flatMap已经存在,没有必要使用不良实践(除了官方函数之外再实现另一个函数)。 - Marwen Trabelsi

60

如果您需要对数组进行映射,并将结果展平,可以使用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]

如果Array.flatMap()不可用,则可以使用Array#concat展开语法来扁平化映射的结果:

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]


1
这很棒。非常聪明地利用了concat如何使用多个数组参数的特性。 - vsync
类型错误:flatMap不是一个函数 我在node v10.18.1中遇到了这个错误。 - U R
它在node v10中不受支持,但有polyfills可用,您也可以使用答案中的[].concat()解决方案。 - Ori Drori
2
另一个选择是使用.map().flat() - Willem Mulder

6
根据定义,.map()返回的数组长度与输入数组相同,因此,在需要创建不同长度结果时,它并不是一个好选择。
从效率的角度来看,最好使用for/of并避免创建大量中间数组:
let values = [1,2,3,4];

let result = [];
for (let val of values) {
    result.push(val*val , val*val*val, val+1);
}

如果你想高效地使用数组方法,可以使用.reduce().push()来避免在每次迭代时创建新的数组:

let values = [1,2,3,4]; 

let result = values.reduce((array, val) => {
    array.push(val*val , val*val*val, val+1);
    return array;
}, []);

0

最好使用lodashflatMap函数

 const output = _.flatMap([1,2,3,4], (v, index, arr) => [v *v, v*v*v, v+1])

输出: [ 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5 ]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接