# 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][1, 2, 4, 8, 16]$$, etc.

This function needs to populate the next number in the sequence


itemn=itemn12$itemn=itemn−1∗2$

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

If the array reaches $$2152152^{15}$$ (no idea what this is), reset the array to
its original contents – $$[1,2,4,8,16][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
for (i=0; i<15; i++) {
console.log(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);
}