remove unnecessary data structs Dict+MapArray
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
import { expect, test } from "vitest";
|
||||
import {
|
||||
createDictionary,
|
||||
type Dictionary,
|
||||
deleteEntrySave,
|
||||
forEntry,
|
||||
getEntry,
|
||||
setEntrySave,
|
||||
} from "./Dictionary.ts";
|
||||
|
||||
test("Dictionary", () => {
|
||||
const dict: Dictionary<string, number> = createDictionary([
|
||||
["a", 1],
|
||||
["b", 2],
|
||||
["c", 3],
|
||||
]);
|
||||
setEntrySave(dict, "foo", 42);
|
||||
setEntrySave(dict, "bar", 0);
|
||||
deleteEntrySave(dict, "bar");
|
||||
|
||||
expect(getEntry(dict, "foo")).toBe(42);
|
||||
expect(getEntry(dict, "bar")).toBe(undefined);
|
||||
expect(dict.indices.size).toBe(dict.entries.length);
|
||||
|
||||
let sum = 0;
|
||||
forEntry(dict, (value) => {
|
||||
sum += value;
|
||||
});
|
||||
expect(sum).toBe(48);
|
||||
});
|
||||
|
||||
test("Dictionary don't mutate, when used 'save', while iterating", () => {
|
||||
const dict: Dictionary<string, number> = createDictionary([
|
||||
["a", 1],
|
||||
["b", 2],
|
||||
["c", 3],
|
||||
]);
|
||||
|
||||
let sum = 0;
|
||||
forEntry(dict, (value, _, index) => {
|
||||
if (index < 1) {
|
||||
setEntrySave(dict, "d", 4);
|
||||
setEntrySave(dict, "e", 5);
|
||||
}
|
||||
|
||||
sum += value;
|
||||
});
|
||||
|
||||
expect(sum).toBe(6);
|
||||
expect(dict.indices.size === 5).toEqual(dict.entries.length === 5);
|
||||
|
||||
sum = 0;
|
||||
forEntry(dict, (value, _, index) => {
|
||||
if (index < 1) {
|
||||
deleteEntrySave(dict, "d");
|
||||
deleteEntrySave(dict, "e");
|
||||
}
|
||||
|
||||
sum += value;
|
||||
});
|
||||
|
||||
expect(sum).toBe(15);
|
||||
expect(dict.indices.size === 3).toEqual(dict.entries.length === 3);
|
||||
});
|
||||
@@ -1,95 +0,0 @@
|
||||
export type Dictionary<K, V> = {
|
||||
entries: Array<[K, V]>;
|
||||
indices: Map<K, number>;
|
||||
isIterating: boolean;
|
||||
deleteQueue: Array<K>;
|
||||
setQueue: Array<[K, V]>;
|
||||
};
|
||||
|
||||
export function createDictionary<K, V>(
|
||||
iterable?: Iterable<[K, V]>,
|
||||
): Dictionary<K, V> {
|
||||
const entries = iterable ? [...iterable] : [];
|
||||
const indices = new Map(entries.map(([k], i) => [k, i]));
|
||||
|
||||
return {
|
||||
entries,
|
||||
indices,
|
||||
isIterating: false,
|
||||
deleteQueue: [],
|
||||
setQueue: [],
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteEntry<K, V>(dict: Dictionary<K, V>, key: K): void {
|
||||
const index = dict.indices.get(key);
|
||||
if (index === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const last = dict.entries.length - 1;
|
||||
if (index !== last) {
|
||||
dict.entries[index] = dict.entries[last];
|
||||
dict.indices.set(dict.entries[index][0], index);
|
||||
}
|
||||
|
||||
dict.entries.pop();
|
||||
dict.indices.delete(key);
|
||||
}
|
||||
|
||||
export function deleteEntrySave<K, V>(dict: Dictionary<K, V>, key: K): void {
|
||||
if (dict.isIterating) {
|
||||
dict.deleteQueue.push();
|
||||
} else {
|
||||
deleteEntry(dict, key);
|
||||
}
|
||||
}
|
||||
|
||||
export function setEntry<K, V>(
|
||||
dict: Dictionary<K, V>,
|
||||
[key, value]: [K, V],
|
||||
): void {
|
||||
const index = dict.indices.get(key);
|
||||
if (index === undefined) {
|
||||
dict.indices.set(key, dict.entries.length);
|
||||
dict.entries.push([key, value]);
|
||||
} else {
|
||||
dict.entries[index][1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
export function setEntrySave<K, V>(
|
||||
dict: Dictionary<K, V>,
|
||||
key: K,
|
||||
value: V,
|
||||
): void {
|
||||
if (dict.isIterating) {
|
||||
dict.setQueue.push([key, value]);
|
||||
} else {
|
||||
setEntry(dict, [key, value]);
|
||||
}
|
||||
}
|
||||
|
||||
export function getEntry<K, V>(dict: Dictionary<K, V>, key: K): V | undefined {
|
||||
const index = dict.indices.get(key);
|
||||
return index === undefined ? undefined : dict.entries[index][1];
|
||||
}
|
||||
|
||||
export function forEntry<K, V>(
|
||||
dict: Dictionary<K, V>,
|
||||
callback: (value: V, key: K, index: number) => void,
|
||||
): void {
|
||||
dict.isIterating = true;
|
||||
for (let i = 0; i < dict.entries.length; i++) {
|
||||
callback(dict.entries[i][1], dict.entries[i][0], i);
|
||||
}
|
||||
dict.isIterating = false;
|
||||
|
||||
while (dict.deleteQueue.length > 0) {
|
||||
deleteEntry(dict, dict.deleteQueue.pop()!);
|
||||
}
|
||||
|
||||
while (dict.setQueue.length > 0) {
|
||||
setEntry(dict, dict.setQueue.pop()!);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { box } from "./box.ts";
|
||||
import MapArray from "./MapArray.ts";
|
||||
|
||||
test("MapArray", () => {
|
||||
const mapArray = new MapArray([
|
||||
["a", box(1)],
|
||||
["b", box(2)],
|
||||
["c", box(3)],
|
||||
]);
|
||||
mapArray.set("foo", box(42));
|
||||
mapArray.set("bar", box(0));
|
||||
mapArray.delete("bar");
|
||||
|
||||
expect(mapArray.get("foo")!.value).toBe(42);
|
||||
expect(mapArray.get("bar")).toBe(undefined);
|
||||
expect(mapArray.map.size).toBe(mapArray.array.length);
|
||||
expect(
|
||||
mapArray.entries().reduce(
|
||||
(a, c) => {
|
||||
a[1].value = a[1].value + c[1].value;
|
||||
return a;
|
||||
},
|
||||
["_", box(0)],
|
||||
)[1].value,
|
||||
).toBe(48);
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
import type { Box } from "./box.ts";
|
||||
|
||||
export default class MapArray<K, V> {
|
||||
map: Map<K, Box<V>>;
|
||||
array: Array<[K, Box<V>]>;
|
||||
|
||||
constructor(iterable?: Iterable<[K, Box<V>]>) {
|
||||
this.map = new Map(iterable);
|
||||
this.array = iterable ? [...iterable] : [];
|
||||
}
|
||||
|
||||
delete(key: K): void {
|
||||
if (this.map.delete(key)) {
|
||||
this.array[this.array.findIndex((e) => e[0] === key)] =
|
||||
this.array[this.array.length - 1];
|
||||
this.array.pop();
|
||||
}
|
||||
}
|
||||
|
||||
set(key: K, value: Box<V>): void {
|
||||
if (this.map.has(key)) {
|
||||
this.array.find((e) => e[0] === key)![1] = value;
|
||||
} else {
|
||||
this.array.push([key, value]);
|
||||
}
|
||||
|
||||
this.map.set(key, value);
|
||||
}
|
||||
|
||||
get(key: K): Box<V> | undefined {
|
||||
return this.map.get(key);
|
||||
}
|
||||
|
||||
entries(): Array<[K, Box<V>]> {
|
||||
return this.array;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user