Skip to content

Instantly share code, notes, and snippets.

@qpwo
Created October 31, 2022 10:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qpwo/5b7f068089c8a826b8a709f2fd937407 to your computer and use it in GitHub Desktop.
Save qpwo/5b7f068089c8a826b8a709f2fd937407 to your computer and use it in GitHub Desktop.
typescript big map class (exceeds 2^24 limit)
// https://gist.github.com/qpwo/5b7f068089c8a826b8a709f2fd937407
const JS_MAP_MAX = Math.pow(2, 24)
export default class BigMap<K = unknown, V = unknown> {
maps: Map<K, V>[]
constructor(pairs: null | readonly (readonly [K, V])[]) {
this.maps = [new Map<K, V>(pairs)]
}
set(key: K, value: V) {
const owner = this.owner(key)
if (owner) {
owner.set(key, value)
return this
}
const last = this.maps[this.maps.length - 1]
if (last.size < JS_MAP_MAX) {
last.set(key, value)
return this
}
const m = new Map()
this.maps.push(m)
m.set(key, value)
return this
}
has(key: K) {
return this.owner(key) !== undefined
}
get(key: K) {
const owner = this.owner(key)
return owner ? owner.get(key) : undefined
}
delete(key) {
const map = this.owner(key)
return map ? map.delete(key) : false
}
clear() {
for (let m of this.maps) {
m.clear()
}
this.maps.length = 1
}
get size() {
let size = 0
for (const m of this.maps) {
size += m.size
}
return size
}
forEach(callback: (value: V, key: K, map: Map<K, V>) => void) {
for (const m of this.maps) {
m.forEach(callback)
}
}
*entries() {
for (const m of this.maps) {
for (const e of m.entries()) {
yield e
}
}
}
*keys() {
for (const m of this.maps) {
for (const k of m.keys()) {
yield k
}
}
}
*values() {
for (const m of this.maps) {
for (const v of m.values()) {
yield v
}
}
}
private owner(key: K) {
// reverse order more efficient in most cases
for (let i = this.maps.length - 1; i >= 0; i--) {
const map = this.maps[i]
if (map.has(key)) {
return map
}
}
return undefined
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment