似乎没有办法用另一个数组来扩展一个现有的JavaScript数组,即模仿Python的extend方法。
我想达到以下几点:
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]
我知道有一个a.c concat(b)方法,但它创建了一个新数组,而不是简单地扩展第一个数组。我想要一个算法,有效地工作时,a明显大于b(即一个不复制a)。
注意:这不是“如何将内容追加到数组?”这里的目标是将一个数组的全部内容添加到另一个数组中,并做到“就地”,即不复制扩展数组的所有元素。
你可以创建一个polyfill for extend,如下所示。它会添加到数组中;In-place并返回自身,这样就可以链接其他方法。
如果(Array.prototype。Extend === undefined) {
Array.prototype.extend = function(other) {
this.push。应用(这个参数。长度> 1 ?论据:其他);
返回;
};
}
函数print() {
document.body.innerHTML += [].map。调用(参数,函数(项){
返回typeof item === 'object' ?JSON.stringify(item): item;
})。Join (' ') + '\n';
}
document.body.innerHTML = ";
Var a = [1,2,3];
Var b = [4,5,6];
打印(“Concat”);
print(“(1)”,a.concat (b));
print(“(2)”,a.concat (b));
Print ('(3)', a.c concat(4,5,6));
打印(“\ nExtend”);
print(“(1)”,a.extend (b));
print(“(2)”,a.extend (b));
Print ('(3)', a.extend(4,5,6));
身体{
字体类型:等宽字体;
空白:前;
}
概述
A.push(…b) -有限的,快速的,现代语法
a.push。应用(a, b) -有限,快速
A = a.c concat(b)无限,如果A很大则很慢
For (let I in b) {a push(b[I]);} -无限,如果b很大则很慢
每个代码片段将a修改为用b扩展。
“limited”代码段将每个数组元素作为参数传递,并且可以传递给函数的参数的最大数量是有限的。从这个链接来看,a.push(…b)似乎是可靠的,直到b中有大约32k个元素(a的大小无关紧要)。
相关MDN文档:spread语法,.apply(), .concat(), .push()
速度的考虑
如果a和b都很小,那么每个方法都是快速的,所以在大多数web应用程序中,你会希望使用push(…b)并完成它。
如果你要处理超过几千个元素,你想要做什么取决于情况:
您正在向一个大数组中添加一些元素
→push(…b)非常快
您正在向一个大数组中添加许多元素
→concat比循环略快
您正在向一个小数组中添加许多元素
→concat比循环快得多
您通常只向任何大小的数组添加少量元素
→循环的速度与用于少量添加的有限方法一样快,但即使在添加许多元素时性能不是最好的,它也不会抛出异常
您正在编写一个包装器函数以始终获得最大性能
→你需要动态检查输入的长度并选择正确的方法,也许在循环中调用push(…b_part)(带有大b的切片)。
这让我很惊讶:我认为a=a.concat(b)将能够在a上对b进行很好的memcpy,而不需要像a.push(…b)那样做单独的扩展操作,因此总是最快的。相反,a.push(…b)要快得多,特别是当a很大的时候。
在Linux下的Firefox 88中,我们使用以下方法来测量不同方法的速度:
a = [];
for (let i = 0; i < Asize; i++){
a.push(i);
}
b = [];
for (let i = 0; i < Bsize; i++){
b.push({something: i});
}
t=performance.now();
// Code to test
console.log(performance.now() - t);
参数及结果:
ms | Asize | Bsize | code
----+-------+-------+------------------------------
~0 | any | any | a.push(...b)
~0 | any | any | a.push.apply(a, b)
480 | 10M | 50 | a = a.concat(b)
0 | 10M | 50 | for (let i in b) a.push(b[i])
506 | 10M | 500k | a = a.concat(b)
882 | 10M | 500k | for (let i in b) a.push(b[i])
11 | 10 | 500k | a = a.concat(b)
851 | 10 | 500k | for (let i in b) a.push(b[i])
请注意,Bsize为500000是我的系统上所有方法所接受的最大值,这就是为什么它小于Asize。
所有测试都运行了多次,以查看结果是异常值还是具有代表性。当然,使用performance.now()在一次运行中几乎无法测量快速方法,但是由于慢方法是如此明显,而且两个快速方法都工作在相同的原理上,因此我们不需要麻烦地重复它一堆次来区分细节。
如果任意一个数组都很大,concat方法总是很慢,但只有当它必须执行大量函数调用并且不关心a有多大时,循环才会很慢。因此,循环类似于push(…b)或push。申请小的bs,但如果确实变大了,不要中断;但是,当您接近极限时,concat又快了一点。