Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Created December 3, 2012 23:10
Show Gist options
  • Save rwaldron/4198955 to your computer and use it in GitHub Desktop.
Save rwaldron/4198955 to your computer and use it in GitHub Desktop.
Comparison of MultiMap with and without @NAMEs
// based on https://mail.mozilla.org/pipermail/es-discuss/2012-December/026799.html
import @iterator from '@iter';
class MultiMap {
private @keys, @vals;
constructor(iterable = []) {
this.@keys = [];
this.@vals = [];
for (let [k, v] of iterable) {
this.append(k, v);
}
}
get(key) {
const keys = this.@keys;
const i = indexOfIdentical(keys, key);
return i < 0 ? undefined : this.@vals[i];
}
getAll(key) {
const keys = this.@keys;
const vals = this.@vals;
const arr = [];
for (var i = 0; i < keys.length; i++) {
if (keys[i] is key) {
arr.push(vals[i]);
}
}
return arr;
}
has(key, ...val) {
const keys = this.@keys;
if (val.length == 0) {
return indexOfIdentical(keys, key) >= 0;
} else {
const vals = this.@vals;
for (const [i, k] of keys) {
if (k is key && vals[i] is val[0]) {
return true;
}
}
return false;
}
}
set(key, ...val) {
const keys = this.@keys;
const vals = this.@vals;
var vali = 0;
for (var i = 0; i < keys.length; i++) {
if (keys[i] is key) {
if (vali < val.length) {
vals[i] = val[vali];
vali++;
} else {
keys.splice(i, 1);
vals.splice(i, 1);
i--;
}
}
}
if (vali < val.length) {
this.push(key, ...val.slice(vali));
}
return this;
}
append(key, ...val) {
const keys = this.@keys;
const vals = this.@vals;
val.forEach(e => {
keys.push(key);
vals.push(val);
});
return this;
}
delete(key, ...val) {
const keys = this.@keys;
const vals = this.@vals;
for (let i = 0; i < keys.length; i++) {
if (keys[i] is key && (val.length == 0 || indexOfIdentifical(val, vals[i]) >= 0)) {
keys.splice(i, 1);
vals.splice(i, 1);
i--;
}
}
return this;
}
*groupedItems() {
var seenAlready = new Set();
var keys = this.@keys;
for (var i = 0; i < keys.length; i++) {
if (seenAlready.has(keys[i]))
continue;
seenAlready.add(keys[i]);
yield [keys[i], this.getAll(keys[i])];
}
}
*keys() {
for (var i = 0; i < [email protected]; i++) {
yield this.@keys[i];
}
}
*values() {
for (var i = 0; i < [email protected]; i++) {
yield this.@vals[i];
}
}
*@iterator {
for (var i = 0; i < [email protected]; i++) {
yield [this.@keys[i], this.@vals[i]];
}
}
}
Object.defineProperty(MultiMap.prototype, 'items', {
configurable: true,
writable: true,
value: MultiMap.prototype.@iterator
});
function indexOfIdentical(keys, key) {
for (var i = 0; i < keys.length; i++) {
if (Object.is(keys[i], key)) {
return i;
}
}
return -1;
}
// based on https://mail.mozilla.org/pipermail/es-discuss/2012-December/026799.html
import iterator from '@iter';
import Symbol from '@symbol';
const keysSymbol = new Symbol();
const valsSymbol = new Symbol();
class MultiMap {
constructor(iterable = []) {
this[keysSymbol] = [];
this[valsSymbol] = [];
for (let [k, v] of iterable) {
this.append(k, v);
}
}
get(key) {
const keys = this[keysSymbol];
const i = indexOfIdentical(keys, key);
return i < 0 ? undefined : this[valsSymbol][i];
}
getAll(key) {
const keys = this[keysSymbol];
const vals = this[valsSymbol];
const arr = [];
for (var i = 0; i < keys.length; i++) {
if (keys[i] is key) {
arr.push(vals[i]);
}
}
return arr;
}
has(key, ...val) {
const keys = this[keysSymbol];
if (val.length == 0) {
return indexOfIdentical(keys, key) >= 0;
} else {
const vals = this[valsSymbol];
for (const [i, k] of keys) {
if (k is key && vals[i] is val[0]) {
return true;
}
}
return false;
}
}
set(key, ...val) {
const keys = this[keysSymbol];
const vals = this[valsSymbol];
var vali = 0;
for (var i = 0; i < keys.length; i++) {
if (keys[i] is key) {
if (vali < val.length) {
vals[i] = val[vali];
vali++;
} else {
keys.splice(i, 1);
vals.splice(i, 1);
i--;
}
}
}
if (vali < val.length) {
this.push(key, ...val.slice(vali));
}
return this;
}
append(key, ...val) {
const keys = this[keysSymbol];
const vals = this[valsSymbol];
val.forEach(e => {
keys.push(key);
vals.push(val);
});
return this;
}
delete(key, ...val) {
const keys = this[keysSymbol];
const vals = this[valsSymbol];
for (let i = 0; i < keys.length; i++) {
if (keys[i] is key && (val.length == 0 || indexOfIdentifical(val, vals[i]) >= 0)) {
keys.splice(i, 1);
vals.splice(i, 1);
i--;
}
}
return this;
}
*items() {
for (var i = 0; i < this[keysSymbol].length; i++) {
yield [this[keysSymbol][i], this[valsSymbol][i]];
}
}
*groupedItems() {
var seenAlready = new Set();
var keys = this[keysSymbol];
for (var i = 0; i < keys.length; i++) {
if (seenAlready.has(keys[i]))
continue;
seenAlready.add(keys[i]);
yield [keys[i], this.getAll(keys[i])];
}
}
*keys() {
for (var i = 0; i < this[keysSymbol].length; i++) {
yield this[keysSymbol][i];
}
}
*values() {
for (var i = 0; i < this[keysSymbol].length; i++) {
yield this[valsSymbol][i];
}
}
}
Object.defineProperty(MultiMap.prototype, iterator, {
configurable: true,
writable: true,
value: MultiMap.prototype.items
});
function indexOfIdentical(keys, key) {
for (var i = 0; i < keys.length; i++) {
if (Object.is(keys[i], key)) {
return i;
}
}
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment