如何将一个TypedArray复制到另一个TypedArray中?

28

C#具有高性能的数组复制函数,可以在原地复制数组:

Array.Copy(source, destination, length)

它比手动操作更快,例如:

for (var i = 0; i < length; i++)
    destination[i] = source[i];

我正在寻找一种等效的高性能复制函数,以在 JavaScript 中原地复制 Int32ArrayFloat32Array 数组。但是我找不到这样的函数:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray

最接近的是 copyWithin,它仅在数组内部进行复制。

是否有内置的高性能复制函数适用于TypedArray数组的原地操作?

如果没有,计划B,是否有一个内置的高性能克隆函数?(编辑:看起来slice()就是答案)


你可以使用 Array.join()。 - ZEE
@علاء الدين,“Array.join”?它甚至不返回一个数组。 - trincot
可能是JavaScript中复制数组的值的重复问题。 - Heretic Monkey
4
我不同意这个问题是重复的。这个问题首要询问如何将值复制到一个现有数组中,而那个问题则询问如何创建一个新的数组。(这个问题只能容忍在最后的情况下创建新数组。)在这种情况下,答案似乎是.set;而在那个情况下,答案是.slice。尽管如此,我认为那个问题是一个有用的指针。 - apsillers
我们能否获得一个样本数据集来比较性能测试中的答案? - Vinny M
同意这不是重复问题,因为“原地”设置是问题的一部分。看起来“.set()”就是答案。 - Brendan Hill
3个回答

45
您正在寻找.set,它允许您使用输入数组(或TypedArray)设置一个数组的值,可选择从目标数组的某个偏移量开始:

destination.set(source);
destination.set(source, offset);

或者,要设置输入数组的有限数量:

destination.set(source.slice(limit), offset);

如果你想创建一个新的TypedArray,你可以直接使用.slice

source.slice();

25
顺便说一句,如果你想要提高效率,你可以使用source.subarray(limit)代替slice,这样只创建一个新视图,并且使用相同的底层数据存储(无需中间数据复制)。 - James Wilkins
3
很遗憾,TypesArray.set()方法不接受可选的第三个参数来限制要复制的条目数。因此,目前创建一个中间视图使用source.subarray(limit)似乎是解决该问题的方式。 - Waruyama

9
您可以使用slice(0)来克隆一个数组。
var clone = myArray.slice(0);

您可以将其变成本机方法:

Array.prototype.clone = function() {
    return this.slice(0);
};

性能 链接,与循环相比较


3
“slice” 是一个好的选择。如果这还不够高性能,那么反对者应该反对 JavaScript,而不是信息传递者。 - trincot
2
你不需要0。请查看重复内容:https://dev59.com/rWs05IYBdhLWcg3wCNlG - Heretic Monkey
2
@MikeMcCaughan,实际上0运行得更快,这是一个性能问题。 - Vinny M
谢谢,实际上出于很好的原因,我更喜欢将内容“原地”复制到现有数组中,以最小化内存波动和更新引用的需要。因此,slice() 方法并不理想。性能链接似乎是针对 JS 数组而非 TypedArrays。 - Brendan Hill
我本来想为 TypedArray 设立一个 jsperf,但是被其他事情所分心了。很高兴有人指导了你正确的方向。 - Vinny M
4
请不要扩展原生数组。使用.slice(0)比扩展更慢得多。 - Jack G

6

复制到已存在的TypedArray中:

destination.set(source);
destination.set(source, offset);

克隆到新的TypedArray示例:(这是最快的!)

var source = new Uint8Array([1,2,3]);
var cloned = new Uint8Array(source);

关于使用构造函数的好建议。虽然我想指出,如果克隆数组已经存在(例如您正在使用双缓冲设置),那么.set会更快(根据我的测量为1.5毫秒自身时间与29.8毫秒自身时间),因为它不需要分配内存。(我的测试涉及一对具有10,000个项目的Uint32Arrays,其中包含真实世界用例中的半随机数据) - Lazerbeak12345

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