Skip to content

Commit e96946a

Browse files
committed
[lib] Add keyed array
1 parent 51849f9 commit e96946a

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
export interface KeyedArray<T> {
2+
key(index: number): number;
3+
push(value: T): void;
4+
swap(a: number, b: number): void;
5+
insert(index: number, value: T): void;
6+
remove(index: number): void;
7+
}
8+
9+
const EMPTY: any[] = [];
10+
11+
export function createKeyedArray<T>(
12+
array: () => T[]
13+
): KeyedArray<T> {
14+
let arrayRef: WeakRef<T[]> = new WeakRef(EMPTY);
15+
let lastKeys: number[] = EMPTY;
16+
let lastKey = -1;
17+
const keys = $derived.by(() => {
18+
const arr = array();
19+
if (arrayRef.deref() === arr) {
20+
return lastKeys;
21+
}
22+
arrayRef = new WeakRef(arr);
23+
lastKeys = new Array(arr.length);
24+
for (let i = 0; i < arr.length; i++) {
25+
// NOTE: there is no `wrap-around` behavior
26+
// But i think `Infinity` is unreachable here
27+
lastKeys[i] = ++lastKey;
28+
}
29+
return lastKeys;
30+
});
31+
return {
32+
key(index: number) {
33+
return keys[index]!;
34+
},
35+
push(value) {
36+
lastKeys.push(++lastKey);
37+
array().push(value);
38+
},
39+
swap(a, b) {
40+
const arr = array();
41+
const key = lastKeys[a];
42+
lastKeys[a] = lastKeys[b]!;
43+
lastKeys[b] = key!;
44+
const tmp = arr[a]!;
45+
arr[a] = arr[b]!;
46+
arr[b] = tmp;
47+
},
48+
insert(index, value) {
49+
lastKeys.splice(index, 0, ++lastKey);
50+
array().splice(index, 0, value);
51+
},
52+
remove(index) {
53+
lastKeys.splice(index, 1);
54+
array().splice(index, 1);
55+
},
56+
};
57+
}

0 commit comments

Comments
 (0)