An ES6 array of numbers – Double last number, delete the first number

Posted on

Problem

I’m writing a JavaScript function for an array, based on a geographic sequence. [1,2,4,8,16][1,2,4,8,16], etc.

This function needs to populate the next number in the sequence

itemn=itemn12itemn=itemn12


If there are more than 1010 items in the array, remove the first
(smallest) number.

If the array reaches 215215 (no idea what this is), reset the array to
its original contents – [1,2,4,8,16][1,2,4,8,16].

I have it working, but I feel this could be written more efficiently…

updateSequence() {
  var sequence = this.get("geometricSequence");

  // Modify the sequence here
  function* values(sequence) {
    for (let prop of Object.keys(sequence)) 
    yield sequence[prop];
  }
  let arr = Array.from(values(sequence));

  const lastIndex = arr.length - 1;
  const lastValue = parseInt(arr[lastIndex]) * 2;
  arr.push(lastValue);
  if (lastIndex > 9) {
    arr.slice(0, 1);
  }
  if (lastValue > 32768) {
    arr = [1, 2, 4, 8, 16];
  }
  this.set('geometricSequence', arr);
}

Solution

This will be cleaner if you implement it as a pure function, which takes the sequence as an argument. You can make [1, 2, 4, 8, 16] a default value for that argument, so that you can start the sequence with nothing. Taking this approach, the function simplifies to:

function updateSequence(arr = updateSequence.default) {
  const last = arr[arr.length-1]
  if (last == 32768) return updateSequence.default

  const ret = arr.concat(last * 2)
  return ret.length > 10 ? ret.slice(1) : ret
}
updateSequence.default = [1, 2, 4, 8, 16]

You can test that it works like this:

// test it
var arr = updateSequence()
for (i=0; i<15; i++) {
  console.log(arr)
  arr = updateSequence(arr)
}

which prints the following:

[ 1, 2, 4, 8, 16, 32 ]
[ 1, 2, 4, 8, 16, 32, 64 ]
[ 1, 2, 4, 8, 16, 32, 64, 128 ]
[ 1, 2, 4, 8, 16, 32, 64, 128, 256 ]
[ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ]
[ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
[ 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 ]
[ 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 ]
[ 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 ]
[ 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 ]
[ 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 ]
[ 1, 2, 4, 8, 16 ]
[ 1, 2, 4, 8, 16, 32 ]
[ 1, 2, 4, 8, 16, 32, 64 ]
[ 1, 2, 4, 8, 16, 32, 64, 128 ]

Since obj.get("geometricSequence"); presumably already contains an array, you can skip the whole shenanigans with the iterator and directly work on that. Also, if you change the order of the if statements at the end you can save some work by not doing slices on an array you eventually gonna replace later anyway. So:

updateSequence() {
  let arr = this.get("geometricSequence");

  const lastIndex = arr.length - 1;
  const lastValue = parseInt(arr[lastIndex]) * 2;

  arr.push(lastValue);

  if (lastValue > 32768)
    arr = [1, 2, 4, 8, 16];
  else if (lastIndex > 9)
    arr.slice(0, 1);

  this.set('geometricSequence', arr);
}

Leave a Reply

Your email address will not be published. Required fields are marked *