28

C# has a high performance array copying function to copy arrays in place:

Array.Copy(source, destination, length)

It's faster than doing it manually ie.:

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

I am looking for an equivalent high performance copy function to copy arrays in place, for Int32Array and Float32Array in JavaScript and can find no such function:

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

The closest is copyWithin which only does a copy internally within an array.

Is there a built in high performance copy function for TypedArrays in place?

Plan B, is there a built in high performance clone function instead? (EDIT: looks like slice() is the answer to that)

Yves M.
  • 29,855
  • 23
  • 108
  • 144
Brendan Hill
  • 3,406
  • 4
  • 32
  • 61
  • u can use Array.join() – ZEE Feb 22 '16 at 20:54
  • @علاء الدين, `Array.join`? that does not even return an array. – trincot Feb 22 '16 at 21:01
  • Possible duplicate of [Copying array by value in JavaScript](http://stackoverflow.com/questions/7486085/copying-array-by-value-in-javascript) – Heretic Monkey Feb 22 '16 at 21:02
  • 4
    @MikeMcCaughan I disagree that this question is a duplicate. This question asks first and foremost how to copy values into an *existing array*, while that question asks how to *create a new array*. (This question tolerates the creation of a new array only as a last resort.) In this case, the answer appears to be `.set`; in that case the answer is `.slice`. Nevertheless, I think that other question is a helpful pointer. – apsillers Feb 22 '16 at 21:14
  • Can we get a sample data set to compare the answers in a performance test? – Vinny M Feb 22 '16 at 21:25
  • Agree this is not a duplicate as setting "in place" is part of the question. Looks like ".set()" is the answer. – Brendan Hill Feb 24 '16 at 04:13

3 Answers3

45

You're looking for .set which allows you to set the values of an array using an input array (or TypedArray), optionally starting at some offset on the destination array:

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

Or, to set a limited amount of the input array:

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

If you instead want to create a new TypedArray, you can simply use .slice:

source.slice();
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • 24
    BTW If you're looking for efficiency you might use `source.subarray(limit)` instead of `slice` so only a new view is created and the same underlying data store is used (no intermediate data copy required). – James Wilkins Nov 14 '17 at 01:04
  • 3
    It is really unfortunate that `TypesArray.set()` does not accept an optional third parameter to limit the number of entries to be copied. So currently creating an intermediate view using `source.subarray(limit)` seems to be the way to go. – Waruyama Jan 17 '20 at 06:07
9

You can clone an array using slice(0);.

var clone = myArray.slice(0);

And you can make it a native method:

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

Performance link comparing to loop

Vinny M
  • 762
  • 4
  • 14
  • 3
    [`slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice) is the way to go. If that ain't high performance enough, then the downvoter should downvote JavaScript, not the messenger. – trincot Feb 22 '16 at 20:59
  • 2
    You don't need to `0`. See the duplicate: http://stackoverflow.com/q/7486085/215552 – Heretic Monkey Feb 22 '16 at 21:02
  • 2
    @MikeMcCaughan, actually the 0 runs faster, and this was a performance question. – Vinny M Feb 22 '16 at 22:14
  • Thanks, actually for good reasons my preference is to copy into an existing array "in place" to minimize memory volatility and having to update references. Hence slice() is undesirable. The performance link seems to be for JS arrays, not TypedArrays. – Brendan Hill Feb 24 '16 at 04:09
  • Yeah I intended to set up a jsperf for a TypedArray but got distracted. Glad someone pointed you in the right direction. – Vinny M Feb 24 '16 at 16:42
  • 4
    Please do not extend the native array. It is much much slower than just doing `.slice(0)`. – Jack G Nov 14 '18 at 15:33
6

clone to an exist typedarray:

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

clone to a new typedarray example: (It's fastest!)

var source = new Uint8Array([1,2,3]);
var cloned = new Uint8Array(source);
cuixiping
  • 24,167
  • 8
  • 82
  • 93
  • About using the constructor, good tip. Though I'd like to point out that if the cloned array already exists (ex you are using a double-buffer setup) then `.set` is (by my measurement) 20 times faster (1.5 ms self time vs 29.8 ms self time), as it does not need to allocate memory. (My test involved a pair of Uint32Arrays each with 10,000 items, containing semi-random data in a real-world use-case) – Lazerbeak12345 Feb 11 '22 at 23:28