【问题标题】:How to duplicate elements in a js array?如何复制js数组中的元素?
【发布时间】:2016-01-23 03:44:43
【问题描述】:

复制 javascript 数组中的每个元素的最简单方法是什么(使用“本机”javascript)?

顺序很重要

例如:

a = [2, 3, 1, 4]
// do something with a
a
// a is now [2, 2, 3, 3, 1, 1, 4, 4]

【问题讨论】:

  • 不是首选/推荐/可靠,但也可以使用正则表达式。 a = a.join(',').replace(/(\d+)/g, "$1,$1").split(',').map(Number);
  • @Tushar 好主意。但是,正如您已经假设的那样,我正在寻找一种通用解决方案,该解决方案也适用于甚至可能包含逗号的字符串数组......
  • 这个问题的最佳答案似乎是复杂代码高尔夫游戏。不要使用reduce,意图超级不清楚。有时 for 循环是正确的答案,抱歉。

标签: javascript arrays


【解决方案1】:

我想出了类似于tymeJV's answer的东西

[2, 3, 1, 4].reduce(function (res, current, index, array) {
    return res.concat([current, current]);
}, []);

【讨论】:

  • 我不明白为什么最后两个参数(indexarray)如果我没有看到它们被使用。有人可以解释一下吗?
  • 如何复制10次?
  • [2,3,1,4].reduce((a,i)=>a.concat(i,i),[]) 更容易阅读或a.concat(Array(10).fill(i)),或者如果 i 是一个对象并且您需要克隆则映射
【解决方案2】:

基本上:

a = [2, 3, 1, 4];
b=[];

for(var i = 0; i< a.length;++i){
  b.push(a[i]);
  b.push(a[i]);
}

a=b;

【讨论】:

  • 如果有人想知道哪种方法最好,我做了一个基准测试,这是最快的复制方法,但如果你想复制超过 6 次,请使用嵌套循环为了更有效的复制。 (在具有 100000 个元素的随机数组上测试)
  • 如果避免在每一步中调用 a.length 可以使其更快
  • @SergeiKovalenko 你对此有什么基准吗?因为据我所知a.length 具有 O(1) 复杂性,因为数组长度应该在 JS 中实现为常量。请参阅stackoverflow.com/questions/32850662/… 了解更多信息
  • @morels,您提供的页面中的 benchmarks 脚本有时会显示 .length 11 和 var 11,但主要是 .length 12 和 var 10,这是计算和直接访问值之间的区别.但从来没有 .length
  • 你有公开的资源吗?我真的很感兴趣。我无法复制您的结果,因为我不知道数据来自哪里,抱歉。
【解决方案3】:

基本上你可以在 ES19 中使用flatMap

a = [1, 2, 3, 4];
a.flatMap(i => [i,i]); // [1, 1, 2, 2, 3, 3, 4, 4]

您也可以像这样自定义重复次数:

a = [1, 2, 3, 4];
const dublicateItems = (arr, numberOfRepetitions) => 
    arr.flatMap(i => Array.from({ length: numberOfRepetitions }).fill(i));

dublicateItems(a, 3);

【讨论】:

  • 你可以继续回答。谢谢@Kaiido
  • 为什么这么复杂? a.flatMap(i =&gt; Array(n).fill(i))
  • @ZeyadEtman 你是说 ES10 (ES2019)?
【解决方案4】:

我想你可以这样做:

var duplicated = a.map(function(item) {
    return [item, item];
}).reduce(function(a, b) { return a.concat(b) });

//duplicated: [2, 2, 3, 3, 1, 1, 4, 4]

【讨论】:

  • 不是Map ES6吗?在这种情况下,此解决方案可能存在兼容性问题
  • map + reduce + concat 似乎有点矫枉过正。减少更好。
  • @EricHerlitz -- .map 是 ES5。
  • @EricHerlitz 是的,但是这里是Array.prototype.map,所以只要是标准浏览器或者IE8+都没有问题
【解决方案5】:

我在我的应用程序中遇到了这个问题,所以我创建了这个函数:

function duplicateElements(array, times) {
  return array.reduce((res, current) => {
      return res.concat(Array(times).fill(current));
  }, []);
}

要使用它,只需传递数组,以及您希望元素被复制的次数:

duplicateElements([2, 3, 1, 4], 2);
// returns: [2, 2, 3, 3, 1, 1, 4, 4]

【讨论】:

    【解决方案6】:

    稍微拼接一下。

    var a = [2, 3, 1, 4],
        i = a.length;
    while (i--) {
        a.splice(i, 0, a[i]);
    }
    document.write('<pre>' + JSON.stringify(a, 0, 4) + '</pre>');

    【讨论】:

      【解决方案7】:

      这些函数可能有助于查看 .sort()、.concat()

      function duplicate(arr) {
          return arr.concat(arr).sort()
      } 
      console.log(duplicate([1,2,3,4,5]))
      

      【讨论】:

      • 有问题明确提到顺序很重要。
      【解决方案8】:

      ES6的生活方式(基于axelduch's的回答)

      const arr = [2, 3, 1, 4].reduce((res, current) => [...res, current, current], []);
      
      console.log(arr);

      【讨论】:

        【解决方案9】:

        怎么样?

        for (i=a.length-1;i>=0;i--)a.splice(i,0,a[i]);
        

        向后迭代被低估了,在这种情况下它保持索引不变;)

        【讨论】:

          【解决方案10】:
          0/2  =  0    =  0  |0  =  0
          1/2  =  0.5  =  0.5|0  =  0
          2/2  =  1    =  1  |0  =  1
          3/2  =  1.5  =  1.5|0  =  1
          4/2  =  2    =  2  |0  =  2
          5/2  =  2.5  =  2.5|0  =  2
          6/2  =  3    =  3  |0  =  3
          7/2  =  3.5  =  3.5|0  =  3
          

          |0 视为Math.floor


          在代码中可能如下所示:

          for (let i = 0; i < a.length * 2; i++) {
            a[i] = a[i / 2 | 0]
          }
          

          因为不变性更可取,所以可以这样做:

          function repeatItems(a, n) {
            const b = new Array(a.length * n)
            for (let i = 0; i < b.length; i++) {
              b[i] = a[i / n | 0]
            }
            return b
          }
          

          不可读的 ES6 意大利面条代码:

          const repeatItems = (a, n) => Array.from(Array(a.length * n), (_, i) => a[i / n | 0])
          

          【讨论】:

            【解决方案11】:

            如上所示,有很多方法可以将项目添加到数组中。我已经比较了它,您可以在控制台中自己查看性能。 任何时间都在两个“console.time”之间

            console.clear();
            
            function loopMyArray(){
             var loopArray = new Array(10000);
             for(var i = 0; i < loopArray.length; i++){
               loopArray[i] = i+1;
             }
             console.log(loopArray);
            }
            console.time('loopMyArray');
            loopMyArray();
            console.timeEnd('loopMyArray');
            
            function fillArray(){
             let x = 0;
             let filledArray = new Array(10000).fill(null).map(()=> ++x);
             console.log(filledArray);
            }
            
            console.time('fillArray');
            fillArray();
            console.timeEnd('fillArray');
            
            function keyMyArray(){
             let fromKeyArray = Array.from(Array(10000).keys());
             console.log(fromKeyArray);
            }
            console.time('keyMyArray');
            keyMyArray();
            console.timeEnd('keyMyArray');
            
            function spreadKeysArray(){
             let spreadArray = [...Array(10000).keys()];
             console.log(spreadArray);
            }
            console.time('spreadKeysArray');
            spreadKeysArray();
            console.timeEnd('spreadKeysArray');
            
            console.log(' Start from 1');
            
            function mapKeyArray(){
             //let mapArray = ([...Array(1000).keys()].map(x => x++)); //increment after return
             let mapArray = [...Array(10000).keys()].map(x => ++x);
             console.log(mapArray);
            }
            
            console.time('mapKeyArray');
            mapKeyArray();
            console.timeEnd('mapKeyArray');
            
            function sliceKeyArray(){
             let sliceFirstElementArray = [...Array(10000+1).keys()].slice(1);
             console.log(sliceFirstElementArray);
            }
            console.time('sliceKeyArray');
            sliceKeyArray();
            console.timeEnd('sliceKeyArray');
            
            function calcFromLength(){
             let fromLengthArray = Array.from({length: 10000}, (v, k) => k+1);
             console.log(fromLengthArray);
            }
            console.time('calcFromLength');
            calcFromLength();
            console.timeEnd('calcFromLength');
            
            console.log('======== add a double for every item ========');
            
            function loopDoubleArray(){
             var first5000Array = [...Array(5000+1).keys()].slice(1);
             var double5000Array =[];
            
             for(var i = 0; i< first500Array.length;++i){
               double5000Array.push(first5000Array[i]);
               double5000Array.push(first5000Array[i]);
             }
             console.log(double5000Array);
            }
            console.time('loopDoubleArray');
            loopDoubleArray(); // Whatever is timed goes between the two "console.time"
            console.timeEnd('loopDoubleArray');
            
            function mapDoubleArray(){
             // adding 1,1,2,2,3,3 etc
             let doubleArray = [...Array(10000).keys()].map(x => Math.floor(++x/2) + x%2);
             console.log(doubleArray);
            }
            console.time('mapDoubleArray');
            mapDoubleArray();
            console.timeEnd('mapDoubleArray');
            
            function fromDoubleArray(){
             let fromDoubleArray = Array.from({length: 10000}, (v, x) => Math.floor(++x/2) + x%2);
             console.log(fromDoubleArray);
            }
            console.time('fromDoubleArray');
            fromDoubleArray(); // Whatever is timed goes between the two "console.time"
            console.timeEnd('fromDoubleArray');
            
            function doubleSpreadArray(){
             let keyArray = [...Array(500+1).keys()].slice(1);
             let doubleSpreadArray = [...keyArray,...keyArray];
             console.log(doubleSpreadArray);
            }
            console.time('doubleSpreadArray');
            doubleSpreadArray(); // Whatever is timed goes between the two "console.time"
            console.timeEnd('doubleSpreadArray');
            
            function reduceDoubleArray(){
             let reduceDoubleArray = Array.from({length: 5000}, (v, k) => k+1).reduce((m,i) => m.concat([i,i]), []);
             console.log(reduceDoubleArray);
            }
            console.time('reduceDoubleArray');
            reduceDoubleArray(); // Whatever is timed goes between the two "console.time"
            console.timeEnd('reduceDoubleArray');
            
            

            我比较了一些速度,看起来差别不大。 mapslicefrom 之间的计算速度(10000 项以毫秒为单位)并没有太大的不同(第一个似乎更好一些)。在计算双项数组时使用 reduce 比其他方法要慢得多

            | mapMyArray     | 5,342041016 | 5,21484375  | 8,424804688 | 5,516113281 |
            | sliceKeyArray  | 5,221191406 | 4,854248047 | 6,069091797 | 4,940185547 |
            | calcFromLength | 6,156005859 | 5,988037109 | 6,031982422 | 6,739990234 |
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-11-10
              • 1970-01-01
              • 2016-11-17
              • 2023-01-01
              • 2021-07-24
              相关资源
              最近更新 更多