如何在JavaScript数组中复制元素?

41

如何使用“原生”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
@Tushar 不错的想法。然而,正如你所假设的那样,我正在寻找一个通用解决方案,它也适用于可能甚至包含逗号的字符串数组... - Jan Rüegg
3
这个问题的最佳答案似乎是复杂度代码高尔夫游戏。不要使用reduce函数,因为它可能会让意图变得不清晰。有时候for循环才是正确的答案,抱歉。 - Nathan Cooper
12个回答

43

我想到了与tymeJV的答案类似的东西

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

我不明白为什么最后两个参数(indexarray)需要存在,如果我没有看到它们被使用。有人可以解释一下吗? - MarksCode
如何将其复制十次? - Zhong Ri
4
[2,3,1,4].reduce((a,i)=>a.concat(i,i),[]) 更易读,或者使用 a.concat(Array(10).fill(i)),如果 i 是一个对象且需要克隆则可以使用 map。 - user120242

34

基本上你可以在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);

我回复下面@user120242的评论 为什么要这么复杂? a.flatMap(i => Array(n).fill(i)) 在这里找到它


你可以继续在上面回答。谢谢@Kaiido - Zeyad Etman
7
为什么这么复杂?a.flatMap(i => Array(n).fill(i)) 的意思是将数组a中的每个元素重复n次,并将结果平铺成一个新数组。 - user120242
@ZeyadEtman 你是指ES10(ES2019)吗? - maswerdna
@user120242请检查我的更新答案。 - Zeyad Etman

17

基本上:

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

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

a=b;

2
如果有人想知道哪种方法最好,我进行了基准测试,这是最快的复制方式,但如果您想要复制超过6次,请使用嵌套循环以实现更高效的复制。(在具有100000个元素的随机数组上进行了测试) - Noel Nemeth
如果避免在每一步调用a.length,就可以使它更快。 - Sergei Kovalenko
@SergeiKovalenko,你对此有任何基准吗?因为据我所知,a.length的复杂度应为O(1),因为JS中数组长度应实现为常数。请参见https://dev59.com/AVwY5IYBdhLWcg3wPFuo以获取更多信息。 - morels
@morels,你提供的页面中的基准测试脚本有时显示.length 11和var 11,但大多数情况下显示.length 12和var 10,这是计算和直接访问值之间的差异。但是,.length从未小于var。 - Sergei Kovalenko
你有公开的数据源吗?我真的很感兴趣。抱歉,我无法复制你的结果,因为我不知道数据来自哪里。 - morels

6

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

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]

1
ES6版本:return [...res,...Array(times).fill(current)]; - mekb

5
我想你可以这样做:

我猜你可以这样:

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]

1
“Map” 不是 ES6 吗?如果是的话,这种解决方案可能存在兼容性问题。 - Eric Herlitz
map + reduce + concat 似乎有些过度了,只用 reduce 更好。 - James
1
@EricHerlitz -- .map 是 ES5。 - tymeJV
@EricHerlitz 是的,但在这里,它是 Array.prototype.map,只要是标准浏览器或IE8+,就没有问题。 - axelduch

2

使用循环和push非常基本的代码片段。

这是一个动态函数,因此您可以指定复制器来重复值的数量。

函数名称duplicate

语法:duplicate (array, duplicator)

  • 数组要传递给函数的数组。
  • duplicator要传递的整数值以重复次数。

它的工作原理:函数接受两个参数数组和duplicator,它基于duplicator构建新数组并返回新构建的数组。

代码片段

function duplicate(array, duplicator){
        var buildArray = [];
        for(i=0; i<array.length; i++){
                for(j=0; j<duplicator; j++){
                        buildArray.push(array[i]);
                }
        }
        return buildArray;
}

使用方法

var a = [2, 3, 1, 4];
var result = duplicate(a, 2);
console.log(result);

根据您的需求更改复制器值以获得所需的输出。
参考: push()

2

基于axelduch的回答,介绍ES6编程方式

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

console.log(arr);


1
这些函数可能有助于查看.sort(),.concat()。
function duplicate(arr) {
    return arr.concat(arr).sort()
} 
console.log(duplicate([1,2,3,4,5]))

问题中明确提到“顺序很重要”。 - Durga

1

怎么样?

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

反向迭代往往被低估,但在这种情况下它可以保持索引不变 ;)


1

只需拼接一点。

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


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