S.Serpooshan
S.Serpooshan

Reputation: 8388

How to store last N values in an array with auto loop to first item when pass last item?

Is there a standard method to have special Array which can store last N elements (probably with an internal index to keep current item) such that when it reaches to and pass the last index, it goes to beginning and over-write the most old items. This way we have always the last recent N items. This is useful for example to store recent 10 price values of a product.

I can write a custom function may be like as below but i guess there may be some built-in method for it as it has many uses.

var n = 10; //max number of elements 
var a = new Array(n); //init the array
var i = 0; //current position

function setNext(value) 
{ 
    i++; if(i >= n) i=0;
    a[i] = value;
}

function getLast() 
{ 
    return a[i];
}

function getAll() 
{ 
    //return concat(a[i+1...n], a[0...i]);  //all items from old to new ones
}

Sample data:

// consider n = 10
// assume we set 10 numbers in array, 
setNext(101);
setNext(102);

//now a is:
a = [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]; // cur index: 9

//now, if we add another value like as 111, it should take 
// position of oldest item of list which is currently 101:
a = [ *111*, 102, 103, 104, 105, 106, 107, 108, 109, 110]; //cur index: 1

Upvotes: 1

Views: 912

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386550

You could splice the array and add the last item to the end.

function lastN(limit, array = []) {
    if (array.length > limit) array.splice(0, array.length - limit);
    const
        fluent = {
            add: value => {
                if (array.length >= limit) array.splice(0, array.length - limit + 1);
                array.push(value);
                return fluent;
            },
            getAll: () => array
        };
    return fluent;
}

const
    five = lastN(5),
    two = lastN(2, ['a', 'b', 'c', 'd', 'e']);

console.log(...five.getAll());
five.add(0);
console.log(...five.getAll());
five.add(1);
console.log(...five.getAll());
five.add(2);
console.log(...five.getAll());
five.add(3);
console.log(...five.getAll());
five.add(4);
console.log(...five.getAll());
five.add(5);
console.log(...five.getAll());
five.add(6);
console.log(...five.getAll());
five.add(7);
console.log(...five.getAll());

console.log('---')
console.log(...two.getAll());
two.add('f');
console.log(...two.getAll());
two.add('g');
console.log(...two.getAll());
two.add('h');
console.log(...two.getAll());
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Kousha
Kousha

Reputation: 36189

Not directly, but you could create a function that reads the array and uses the modulo % to perform this operation, something like

const n = 10;
const array = new Array(n);

const get = (a, index) => a(index % a.length);

// all three are the same item
const elem1 = get(array, 1);
const elem2 = get(array, 11);
const elem3 = get(array, 21);

Basically, we are using % to calculate the remainder which would act like a "loop" as you put it:

0 % 10 = 0 // first element
1 % 10 = 1 // second element
...
10 % 10 = 0 // Looped once, gives first element again
11 % 10 = 1 // Looped once, gives the second element
...
20 % 10 = 0 // Looped twice, gives first element again

Upvotes: 0

Related Questions