Skip to content

Instantly share code, notes, and snippets.

@julien-f
Created April 26, 2021 11:49
Show Gist options
  • Save julien-f/026c0a033703ef1bdab6557536b38dde to your computer and use it in GitHub Desktop.
Save julien-f/026c0a033703ef1bdab6557536b38dde to your computer and use it in GitHub Desktop.
MultiMap implementation for ECMAScript/JavaScript
export class MultiMap {
#entries = new Map()
#size = 0
get size() {
return this.#size
}
clear() {
this.#entries.clear()
this.#size = 0
}
delete(key, value) {
const entries = this.#entries
const values = entries.get(key)
if (values === undefined) {
return false
}
if (arguments.length < 2) {
this.#size -= values.size
return entries.delete(key)
}
if (!values.delete(value)) {
return false
}
--this.#size
if (values.size === 0) {
entries.delete(key)
}
return true
}
*entries() {
for (const [key, values] of this.#entries.entries()) {
yield [key, values.values()]
}
}
forEach(callbackFn, thisArg) {
for (const [key, values] of this.#entries.values()) {
for (const value of values.values()) {
callbackFn.call(thisArg, key, value, this)
}
}
}
get(key) {
return (this.#entries.get(key) ?? Array.prototype).values()
}
has(key, value) {
const entries = this.#entries
if (arguments.length < 2) {
return entries.has(key)
}
const values = entries.get(key)
return values !== undefined && values.has(value)
}
keys() {
return this.#entries.keys()
}
set(key, value) {
const entries = this.#entries
const values = entries.get(key)
if (values === undefined) {
entries.set(key, new Set([value]))
} else {
values.add(value)
}
++this.#size
return this
}
*values() {
for (const values of this.#entries.values()) {
yield* values.values()
}
}
[Symbol.iterator]() {
return this.entries()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment