【问题标题】:Array.map 1 element to multiple elementArray.map 1 个元素到多个元素
【发布时间】:2019-12-05 06:50:20
【问题描述】:

我有[3, 16, 120]。当我做[3, 16, 120].map(mapper)时,我想实现,例如[4,5, 17,18, 121,122],即每个元素映射到n+1和n+2。这当然是一个例子 - 我想要的是简单地从映射器函数中推送多个值

我是否必须使用 Array.each 并推送到一个数组,或者是否可以使用 Array.map(或其他内置 api)来做到这一点

【问题讨论】:

  • 你可以使用Array.reduce,虽然我不确定它是否比使用Array.forEach更好。

标签: javascript map-function


【解决方案1】:

您可以使用reduce() 并将每个元素的e+1, e+2 添加到数组中。

var ar = [3, 16, 120];

var result = ar.reduce(function(r, e) {
  r.push(e+1, e+2);
  return r;
}, []);

console.log(result)

这是带有箭头功能的 ES6 版本

var ar = [3, 16, 120];

var result = ar.reduce((r, e) => r.push(e+1, e+2) && r, []);
console.log(result)

PS:Array.push 似乎更快,没有Maximum call stack.. 错误,见下文:

a = Array(1000000).fill(1); st = Date.now(); Array.prototype.concat.apply([], a.map(function (n) { return [n+1, n+2]; })); console.log(`${Date.now() - st}ms `);
> RangeError: Maximum call stack size exceeded

a = Array(1000000).fill(1); st = Date.now(); a.reduce((r, e) => r.push(e+1, e+2) && r, []); console.log(`${Date.now() - st}ms `);
> 180ms

因此,与公认的解决方案相比,.push 更可取。

【讨论】:

  • 你在回调中修改r,这意味着这只是一个不必要的复杂for循环。
  • 我刚刚添加了性能测试来回答,在这种情况下,与.concat 相比,.push 似乎更可取。 concat 还会为大数组抛出 Maximum call stack 异常
【解决方案2】:

我自己想出了一个,使用扩展运算符。

[].concat(...[3, 16, 120].map(x => [x+1, x+2]))

【讨论】:

    【解决方案3】:

    2019 年更新

    使用Array.prototype.flatMap(),在 ES10 中引入。

    const oddNumbers = [1, 3, 5, 7, 9];
    const allNumbers = oddNumbers.flatMap((number) => [number, number + 1]);
    console.log(allNumbers); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    【讨论】:

      【解决方案4】:

      不是特别好,但这是一个可能的解决方案:

      var arr = [3, 16, 120];
      
      console.log([].concat.apply([], arr.map(function (n) { return [n+1, n+2]; })));

      【讨论】:

      • 您应该考虑使用Array.prototype.concat 而不是[].concat。它更短,但每次运行时您都会分配一个新数组
      • @eltonkamami 我已经分配了 n+3 个数组。 n+4 不会让事情变得更糟。
      【解决方案5】:

      您可以为每个项目生成一个数组,然后连接所有这些数组:

      [3, 16, 120].map(x => [x+1, x+2] ).reduce( (acc,val) => acc.concat(val), []);
      

      【讨论】:

      • 不错,但它执行了 2 次数组传递和双倍数组
      • 是的,我认为@Nenad Vracar 的解决方案比我的好
      【解决方案6】:

      您可以将Array#reduceArray#concat 结合使用。

      console.log([3, 16, 120].reduce(function (r, a) {
          return r.concat(a + 1, a + 2);
      }, []));

      ES6

      console.log([3, 16, 120].reduce((r, a) => r.concat(a + 1, a + 2), []));

      【讨论】:

        【解决方案7】:

        不可变的解决方案,使用扩展运算符:

        [3, 16, 120].reduce((a, v) => [...a, v+1, v+2], [])
        

        【讨论】:

          【解决方案8】:

          使用Array#concatArray#map

          Array.prototype.concat.apply([], [3, 16, 120].map(x => [x+1, x+2] ));
          

          【讨论】:

            【解决方案9】:

            只是为了好玩,一个带有生成器的 ES6 解决方案:

            var arr = [3, 16, 120];
            
            var [...result] = (function*() { for( i of arr){ yield ++i; yield ++i; }})();
            
            console.log(result);

            【讨论】:

            • 我从来不知道这可以工作... 1. 生成器可以使用扩展运算符扩展(嗯,它是可迭代的) 2. 扩展运算符比赋值慢 好一个!
            【解决方案10】:

            使用 Array.prototype.flat():

            const doubled = [3, 16, 120].map(item => [item + 1, item + 2]).flat();
            
            console.log(doubled)

            公平警告 - 迄今为止还不是标准方法(2018 年 12 月发布)。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-05
              • 1970-01-01
              • 2015-11-13
              • 2015-08-13
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多