2

I have a typed Javascript Array (Float32Array) and I want to insert one value at a time at the beginning of the array and move all other values by one position (the last value gets deleted).

Here is an example:
Let's say I have initialized the array with a size of 3. The array currently holds the values [2.0, 7.2, 4.5] and I want to insert the number 8.1. The result should be [8.1, 2.0, 7.2].

If I would use a normal JS array this would no problem – I could use functions like .unshift() or .pop(), but these methods don't work on typed JS arrays, because they change the size of the array.

Is there a way to efficiently implement this using a typed Javascript Array?

2 Answers 2

2

Here is a method that don't involves using a loop (on your end).

  • Using subarray use the same underlying ArrayBuffer instead of allocating a new buffer
  • compared to Mr. Polywhirl this two functions are just about shifting values any number of steps you like and don't involve inserting any values since i think this could benefit other use cases as well and make this two function more "pure". so it fits the name shift Left/Right better
  • Is subarray + set + fill faster/more memory friendly? i don't know

const shiftRight = (collection, steps = 1) => {
  collection.set(collection.subarray(0, -steps), steps)
  collection.fill(0, 0, steps)
  return collection
}

const shiftLeft = (collection, steps = 1) => {
  collection.set(collection.subarray(steps))
  collection.fill(0, -steps)
  return collection
}

const float32 = new Float32Array([2.0, 7.2, 4.5]);

shiftRight(float32) // >>> [ 0, 2.0, 7.2 ]
float32[0] = 8.1 // [ 8.1, 2.0, 7.2 ] Place new value at head
console.log(float32)

shiftLeft(float32) // <<< [ 2.0, 7.2, 0 ]
float32.fill(4.5, -1) // [ 2.0, 7.2, 4.5 ] Place new value at tail
console.log(float32)

shiftRight(float32, 2) // >>> [ 0, 0, 2.0 ] shift right 2 steps
console.log(float32)

Sign up to request clarification or add additional context in comments.

Comments

1

You can "unshift" a value on a fixed array by shifting all the value at the end to the right by 1. After you have done that, you just replace the head with the value parameter. Traditional for-loops are going to be the most efficient way to do this.

The key here is to loop backwards, filling the last slot with its neighbor to the left.

Works for all the indexed collections:

  • Array
  • Int8Array, Uint8Array, Uint8ClampedArray
  • Int16Array, Uint16Array
  • Int32Array, Uint32Array
  • Float32Array, Float64Array
  • BigInt64Array, BigUint64Array

As you already know, TypedArray objects do not have all the methods available on standard Array objects.

const shiftRight = (collection, value) => {
  for (let i = collection.length - 1; i > 0; i--) {
    collection[i] = collection[i - 1]; // Shift right
  }
  collection[0] = value; // Place new value at head
  return collection;
}

const shiftLeft = (collection, value) => {
  for (let i = 0; i < collection.length - 1; i++) {
    collection[i] = collection[i + 1]; // Shift left
  }
  collection[collection.length - 1] = value; // Place new value at tail
  return collection;
}

const float32 = new Float32Array([2.0, 7.2, 4.5]);

console.log(shiftRight(float32, 8.1)); // >>> [ 8.1, 2.0, 7.2 ]
console.log(shiftLeft(float32, 4.5));  // <<< [ 2.0, 7.2, 4.5 ]
.as-console-wrapper { top: 0; max-height: 100% !important; }

Usually you do not want to pollute the prototype with additional methods, but if you are calling this everywhere, you could devise the following:

shiftRight=(c,v)=>{for(i=c.length-1;i>0;i--)c[i]=c[i-1];c[0]=v;return c}
shiftLeft=(c,v)=>{for(i=0;i<c.length-1;i++)c[i]=c[i+1];c[c.length-1]=v;return c}

/* Needs to be added to all the various indexed collections */
if (Float32Array.prototype.shiftRight === undefined) {
  Float32Array.prototype.shiftRight = function(value) {
    return shiftRight(this, value);
  };
}
if (Float32Array.prototype.shiftLeft === undefined) {  
  Float32Array.prototype.shiftLeft = function(value) {
    return shiftLeft(this, value);
  };
}

const float32 = new Float32Array([2.0, 7.2, 4.5]);

console.log([...float32.shiftRight(8.1).values()]); // >>> [ 8.1, 2.0, 7.2 ]
console.log([...float32.shiftLeft(4.5).values()]);  // <<< [ 2.0, 7.2, 4.5 ]
.as-console-wrapper { top: 0; max-height: 100% !important; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.