Skip to content

Instantly share code, notes, and snippets.

@DScheglov
Created April 15, 2025 20:54
Show Gist options
  • Save DScheglov/df4915124772cc9913fd241ddcfee36b to your computer and use it in GitHub Desktop.
Save DScheglov/df4915124772cc9913fd241ddcfee36b to your computer and use it in GitHub Desktop.
Floating Window Average
class FixedSizeBuffer<T> {
#buffer: T[];
#maxSize: number;
#index: number = 0;
#count: number = 0;
static of<T>(size: number) {
return new FixedSizeBuffer<T>(size);
}
constructor(size: number) {
this.#maxSize = size;
this.#buffer = new Array<T>(size);
}
push(value: T): { value: T } | null {
let evicted: { value: T } | null = null;
if (this.#count < this.#maxSize) {
this.#count++;
} else {
evicted = { value: this.#buffer[this.#index] }
}
this.#buffer[this.#index] = value;
this.#index++;
if (this.#index === this.#maxSize) this.#index = 0;
return evicted;
}
get size(): number {
return this.#count;
}
*[Symbol.iterator](): IterableIterator<T> {
const total = this.#count;
if (total === 0) return;
const maxSize = this.#maxSize;
const isNotFull = total < maxSize;
const start = isNotFull ? 0 : this.#index;
const end = isNotFull ? total : maxSize;
for (let i = start; i < end; i++) yield this.#buffer[i];
if (isNotFull) return;
for (let i = 0; i < this.#index; i++) yield this.#buffer[i];
}
}
const movingAverage = (buffer: FixedSizeBuffer<number>) => {
let sum = 0;
for (const item of buffer) sum += item;
return (value: number) => {
const evicted = buffer.push(value);
if (evicted != null) sum -= evicted.value;
sum += value;
return sum / buffer.size;
};
}
const buf = FixedSizeBuffer.of<number>(3);
const acc = movingAverage(buf);
const input = [
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
];
for (const value of input) {
console.log('Adding value:', value, 'to', [...buf]);
const avg = acc(value);
console.log([...buf], avg);
}
@DScheglov
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment