在JavaScript中将一个数组复制任意次数

16

假设我有一个数组。这个数组的长度为3,有3个元素:

var array = ['1','2','3'];

最终,我需要检查这个数组是否等于一个包含相同元素的数组,只是现在有两倍大小。我的新数组是:

var newArray = ['1','2','3','1','2','3'];
我知道我可以使用array.splice()来复制一个数组,但是如何将其复制未知的次数?基本上我想要的是具有以下效果的东西
var dupeArray = array*2;

你需要一个函数来比较两个数组还是从给定的数组生成一个新数组? - Trott
var arr=[1,2,3]; arr.map([].valueOf.bind(arr)) - dandavis
@Trott 我有一个比较两个数组元素的函数。我想要的是一个从给定数组中生成未知数量新数组的函数。 - kjsmita6
2
在你复制的时候,你应该知道想要“复制”多少次,对吧?为什么不能只是多次使用concat/splice/其他方法呢? - slifty
1
最终我需要检查这个数组是否等于另一个有相同元素但是两倍大的数组。这是否是你所谓的 XY 问题中的 X?换句话说,这是你的最终目标吗? - Shashank
9个回答

14
const duplicateArr = (arr, times) =>
    Array(times)
        .fill([...arr])
        .reduce((a, b) => a.concat(b));

这应该可行。它创建一个大小为您想要重复的次数的新数组。它使用数组的副本填充它。然后使用reduce将所有数组连接成单个数组。


1
我们现在有.join()来替代reduce - kano
1
@kano .join() 输出一个字符串,你是不是想用 flat() - Leon Segal
是的,我做到了,谢谢!这只是一个愚蠢的瞬间... 扇耳光 - kano

5

最简单的解决方案常常是最好的方案:

function replicate(arr, times) {
     var al = arr.length,
         rl = al*times,
         res = new Array(rl);
     for (var i=0; i<rl; i++)
         res[i] = arr[i % al];
     return res;
}

您可以使用嵌套循环,例如@UsamaNorman所示。

但是,如果您想要更聪明的方法,您也可以重复使用concat将数组连接到其自身:

function replicate(arr, times) {
    for (var parts = []; times > 0; times >>= 1) {
        if (times & 1)
            parts.push(arr);
        arr = arr.concat(arr);
    }
    return Array.prototype.concat.apply([], parts);
}

1
可能应该是 res = new Array(rl);,对吧?还有在 for 循环中应该是 i < rl。不管怎样,我已经点赞了。 - Shashank

3

虽然基础,但对我有用。

var num = 2;

while(num>0){
array = array.concat(array);
num--}

1
如果您在循环中,可以通过数组长度来验证当前循环索引,然后乘以其内容。
let arr = [1, 2, 3];

if(currentIndex > arr.length){ 
  //if your using a loop, make sure to keep arr at a level that it won't reset each loop

  arr.push(...arr);

}

完整示例: https://jsfiddle.net/5k28yq0L/


1

你可以做:

var array = ['1','2','3'];


function nplicate(times, array){
      //Times = 2, then concat 1 time to duplicate. Times = 3, then concat 2 times for duplicate. Etc.
     times = times -1;
     var result = array;

    while(times > 0){
        result = result.concat(array);
        times--;
    }

    return result;
}

console.log(nplicate(2,array));

你需要将同一个数组连接n次。
使用concat函数和一些逻辑:http://www.w3schools.com/jsref/jsref_concat_array.asp

谢谢,现在可以了吗?我已经编辑过了。对于我的错误感到抱歉。但是我知道如何编写一个函数来将数组连接 n 次。 - Juan Marcos Armella

1

这是一种相对简洁的,非递归的方法来复制一个数组任意次数:

function replicateArray(array, n) {
  // Create an array of size "n" with undefined values
  var arrays = Array.apply(null, new Array(n)); 

  // Replace each "undefined" with our array, resulting in an array of n copies of our array
  arrays = arrays.map(function() { return array });

  // Flatten our array of arrays
  return [].concat.apply([], arrays);
}

console.log(replicateArray([1,2,3],4)); // output: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

发生了什么?

前两行使用 applymap 来创建 一个由 "n" 个副本组成的数组

最后一行使用 apply 来展开 我们最近生成的数组。

但是,真的发生了什么?

如果你没有使用过 apply 或 map,这段代码可能会让人感到困惑。

这里的第一个神奇部分是使用 apply(),它可以将一个数组作为参数列表传递给函数。

Apply 使用三个信息: x.apply(y,z)

  • x 是被调用的函数
  • y 是函数所在的对象(如果为null,则使用global
  • z 是参数列表

代码示例:y.x(z[0], z[1], z[2],...)

例如

var arrays = Array.apply(null, new Array(n));

就等同于写作:

var arrays = Array(undefined,undefined,undefined,... /*Repeat N Times*/);

第二个神奇的部分是使用map(),它对数组中的每个元素调用一个函数并创建返回值列表。
这里使用了两个信息:x.map(y)
  • x是一个数组
  • y是一个要在数组的每个元素上调用的函数
例如:
var returnArray = [1,2,3].map(function(x) {return x + 1;});

会创建数组[2,3,4]。
在我们的情况下,我们传递了一个始终返回静态值(即我们要复制的数组)的函数,这意味着此map的结果是我们的数组的n个副本的列表。

代码有些棘手,但很难跟踪它的功能。就我而言,我更喜欢任何人都能立即看到其功能的代码。在我的书中,简洁并不会得到额外的分数,而清晰易懂则会得到加分。 - jfriend00
好的!我只是结合了SO上的答案,展示了如何查找子问题来构建一个复合答案。我会再详细解释一下。 - slifty
更新加详细解释。唉,也许applymap只是一些高级概念,可能很难指望每个人一眼就能理解。 - slifty

1
保持简短而精炼
function repeat(a, n, r) {
    return !n ? r : repeat(a, --n, (r||[]).concat(a));
}

console.log(repeat([1,2,3], 4)); // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

http://jsfiddle.net/fLo3uubk/


2
更加简短而优美的代码:function replicate(a, n) { return !n ? [] : repeat(a, n-1).concat(a); } - Bergi
@Bergi 很好!只是不要忘记用“复制”替换“重复”;-) - Shahriar

0

我认为你需要编写自己的函数,试试这个:

function dupArray(var n,var arr){
var newArr=[];
for(var j=0;j<n;j++)
    for(var i=0;i<arr.length;i++){
        newArr.push(arr[i]);
    }
return newArr;
}

使用方法如下:myArr = dupArray(5,previousArr); - Usama Noman
有比嵌套for循环更好的方法!此外,您可能希望编辑您的答案以包括用法,而不是将其编写为注释。 - slifty
@slifty:更好的方法比如? - Bergi
1
不错的选择 ;) -- 例如 Array.concat https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat -- 比如 https://dev59.com/cmgv5IYBdhLWcg3wD8yY - slifty

0

检查重复的一个相对简单的解决方案是...

您可以使用模数检查长度的变化:

然后,如果可能的话,请循环遍历内容并比较每个值,直到完成。如果在结束之前任何时候不匹配,则它要么没有重复,要么在结束之前停止了重复。

if (array2.length % array1.length == 0){
    // It might be a dupe
    for (var i in array2){
        if (i != array1[array2.length % indexOf(i)]) { // Not Repeating }
    }
}

当您使用“for var i in array2”语法时,您正在循环遍历array2的索引。因此,这个答案真的很混乱。也许在这里使用Array.prototype.forEach会更优雅。使用模数是解决这个问题的好方法,所以我喜欢你答案中的那部分。 - Shashank

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