Skip to content

Instantly share code, notes, and snippets.

@asleepace
Created December 11, 2024 05:49
Show Gist options
  • Save asleepace/eb2df968c7c3ab3f8de709f1b51c6782 to your computer and use it in GitHub Desktop.
Save asleepace/eb2df968c7c3ab3f8de709f1b51c6782 to your computer and use it in GitHub Desktop.
/**
* Key / Value container which enforces a max capacity and
* provides several methods for iteration.
*
* Demo:
* https://www.typescriptlang.org/play/?target=99#code/PQKhCgAIUyGkCmBPSxIDUCGAbArgyAYwHsA7AF0wEtSEAnSAdwAsrDnIFSAzYuwhAGdImSAFtMADyKYADpkJVyKTKQAmUGJFl1iANypqhkQQj30c4hOWbE1w3gyUXyVMgDpIm4OELZMgsIAgnR0mEgAsnIAPAAqALyqSAB8kADe4FCw2nRUepjkBBKSAMJyCkpIAFyQpLhiAEb0kPGQACxZsDp5BQQ0pnTkAPJ0RnQ1guS5pADmANoAui2Qi505PYUm5HwINQBKCCSj0ZPTMwA0kLGprWkAvpnZ2rgN2GyQM9ZExLgUABQAShqdUazQyTyedGsuDopEgQwaACtDuR3ABrZCCP42KiCdyTHYA9zYLgzGxrB5rUAQCEwADKXxsBAxSGA+TwBHkVAYqjUTCo2GwnAMhHIkGI2DGnAouSEa2gkCo3HEUhk8kUykVwihCmYCDUngAksrVMK2K4yOLCIQYcJ5TAccJGAKhThBMRIFDyDC4UyzaL9ZB2fh3PafE9ZC83oQTNY-iyJlMaBcgzh8DVYkCrpAAD5B4iGdLy7KO9z9ejDUb0dy-QSsbjkePIAHF2ClglQuYspatYMIVtMVgkyDY1h4ki-MWpUvFMrqyoAosQ5ffUiTTiSWTc-WIFCtUvlwYjMbuWTEWSAgdPJUjhCb7dqXeQABkz43W6hj+Qit9Y-x2yhRdwRXECSDXMU7w-fUsA5ZZ2wAhA5kgh9dwWK8VyMElNngnYkPvT9UPQ5cvR9d8Hxg-AiMgB4QJo7JKQjKN3k+RsEy2M4s1iXNIF+IxuBoQNgOI6FYUgHDO27ClHmySNXneKExH0BAm2qdjkyzBpiAlBBTSEiEsMgNRDAORTzGWbg3X7ECDzXCtj2afc-0PSsT347BCjoP4-g7HdmxaVI9JAm8VJaeJWh8r8kCAqinkw6wCHExDJJAkCjLUEylLguhKJSlcSNEqYcty6jOGwUwl2KyERLhCyyqs4q6OXO4WxA-K4TSjLzCktZZOjERBUBDNFgq4TvQKpzbKPKs6HcCQLxUxd4mnP8fK7ZAFha+jpK6JiYz8HTPKzPQCz5QKSxWhDlnuAcbIGFyHJWNCngYmTdpVC9CBwbAGgUNEaj+GhI3IDNFtSTMhqWM7YDasSJru+yZrmryWVBkaUrA9dnDEOCLtw5LioxsVaEkMVWk+wUfsINEAcKMRNtyxK1qQHtajvcgqJh4n2do+nqO2545JjNyPL+cnvt+-61AKTAQf8yBNO01ROOGqHYdxMtJvuhhHPV5yEfcYX6GRvylrR0CyHXPscfV1b8dywmtQAMQFDzAzJr7KepvteZAqjgtxZ33PofVF1LBSlIW-nWuqp2XeDjQeakylgDQABRSRMDEWRh1wQRME+TIHc+9gCFaWhGEgEIwkiGIQSaOhkkvYu9XxOMACIpcoABGNvLi7gAmABmFtm4QVvGw76X+979ou4AVhH3Ux9MCfO8wQeZ4ANgAdgADkXkvx7+SfKDaGeAE4u4ABgPluV+Pte55nruX5Hi3tOJYgZlFpf3C+wFb5j32pgQ6vh34kk-t-Uef8BoAkAUfE+mBN7PyHi2Xwv8kY0wQHTOWWMFT9zQRjD+2Av4-0Pv-OBQA
*
*/
class ArrayMap<T=any> {
private maxCapacity: number = 4
private insertOrder: string[] = []
private store: Record<string, T> = {}
public get count(): number {
return Object.keys(this.store).length
}
/**
* Set the key/value pair and will evict older entries
* if max capacity is reached. If an eviction occurs
* this will also return the evicted value.
*/
public set(key: string, value: T): T | void {
this.insertOrder.unshift(key)
this.store[key] = value
while (this.count > this.maxCapacity) {
const expiredKey = this.insertOrder.pop()
if (expiredKey && expiredKey in this.store) {
const expiredValue = this.store[expiredKey]
delete this.store[expiredKey]
return expiredValue
}
}
}
public get(key: string): T | undefined {
return this.store[key]
}
public remove(key: string): boolean {
let didRemove = false
this.insertOrder = this.insertOrder.filter((storedKey) => {
if (key === storedKey) {
delete this.store[key]
didRemove = true
return true
} else {
return false
}
})
return didRemove
}
public all(): T[] {
return this.insertOrder.map((key) => this.store[key])
}
public clear(): void {
this.store = {}
this.insertOrder = []
}
public map(callback: (input: T) => T): T[] {
return this.insertOrder.map((key) => {
const item = this.store[key]
const next = callback(item)
this.store[key] = next
return next
})
}
public filter(callback: (data: T) => boolean): T[] {
this.insertOrder = this.insertOrder.filter((key) => {
const value = this.store[key]
const isFiltered = callback(value)
if (isFiltered) this.remove(key)
return isFiltered
})
}
}
// Example usage
const cache = new ArrayMap<number>()
cache.set("data1", 123)
cache.set("data2", 415)
cache.set("data3", 678)
cache.set("data4", 910)
cache.set("data5", 111)
console.log(cache.all())
cache.clear()
console.log(cache.all())
cache.set("data6", 123)
cache.map((item) => item * 2)
console.log(cache.all())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment