Last active
February 18, 2022 14:47
-
-
Save tw3/b6354bae2d4170fc72022f741ea5bb24 to your computer and use it in GitHub Desktop.
Rotates the starting index and ending index when looping over an array multiple times. At any given point you have the option to reset the starting index and have the array loop to the first item after reaching the end of the array(resetAtNextIndex()). Example usage can be found here: https://stackblitz.com/edit/typescript-cfxmnn?file=index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class RotatingIterator<T> implements Iterable<T> { | |
private readonly origStart: number; | |
private nextIndex: number; | |
private isDone: boolean; | |
private hasLooped: boolean; | |
constructor(private readonly arr: T[], private startIndex = 0) { | |
this.origStart = startIndex; | |
this.nextIndex = startIndex; | |
this.isDone = false; | |
this.hasLooped = false; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
get length(): number { | |
return this.arr.length; | |
} | |
next(): IteratorResult<T> { | |
if (!this.isDone) { | |
// We may not be done yet | |
if (!this.hasLooped) { | |
// We have not yet looped | |
if (this.isBeforeEndLoop()) { | |
return this.getNextResult(); | |
} | |
// We need to loop | |
this.hasLooped = true; | |
this.nextIndex = 0; | |
} | |
// We have looped and may not have reached the start | |
if (this.isBeforeStart()) { | |
return this.getNextResult(); | |
} | |
// We have looped and come back to the start | |
this.isDone = true; | |
} | |
// We are done | |
return this.getDoneResult(); | |
} | |
resetAtNextIndex(): void { | |
this.startIndex = this.nextIndex; | |
this.isDone = false; | |
this.hasLooped = false; | |
} | |
resetAtOriginalStartIndex(): void { | |
this.startIndex = this.origStart; | |
this.isDone = false; | |
this.hasLooped = false; | |
} | |
getValueByIndex(idx: number): T { | |
return idx < this.arr.length ? this.arr[idx] : undefined; | |
} | |
private getNextResult(): IteratorResult<T> { | |
const result: IteratorResult<T> = { | |
index: this.nextIndex, | |
value: this.arr[this.nextIndex], | |
done: false, | |
}; | |
// console.log({ this.nextIndex }); | |
this.nextIndex++; | |
return result; | |
} | |
private getDoneResult(): IteratorResult<T> { | |
return { | |
index: undefined, | |
value: undefined, | |
done: true, | |
}; | |
} | |
private isBeforeStart(): boolean { | |
return this.nextIndex < this.startIndex; | |
} | |
private isBeforeEndLoop(): boolean { | |
return this.nextIndex < this.arr.length; | |
} | |
} | |
export interface IteratorResult<T> { | |
index: number; | |
value: T; | |
done: boolean; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For example given an array like this:
[0, 1, 2, 3, 4]
0, 1, 2
resetAtNextIndex()
& iterate 4 more times and stop => accesses items3, 4, 0, 1
resetAtNextIndex()
& iterate until "done" => accesses2, 3, 4, 0, 1
resetAtNextIndex()
& iterate 2 more times => accesses2, 3
4, 0, 1
Seen here: https://stackblitz.com/edit/typescript-efw6th?file=index.ts