|
|
type Key = string | number | symbol; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class SetArray<T extends Key = Key> { |
|
|
declare private _indexes: Record<T, number | undefined>; |
|
|
declare array: readonly T[]; |
|
|
|
|
|
constructor() { |
|
|
this._indexes = { __proto__: null } as any; |
|
|
this.array = []; |
|
|
} |
|
|
} |
|
|
|
|
|
interface PublicSet<T extends Key> { |
|
|
array: T[]; |
|
|
_indexes: SetArray<T>['_indexes']; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function cast<T extends Key>(set: SetArray<T>): PublicSet<T> { |
|
|
return set as any; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function get<T extends Key>(setarr: SetArray<T>, key: T): number | undefined { |
|
|
return cast(setarr)._indexes[key]; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function put<T extends Key>(setarr: SetArray<T>, key: T): number { |
|
|
|
|
|
const index = get(setarr, key); |
|
|
if (index !== undefined) return index; |
|
|
|
|
|
const { array, _indexes: indexes } = cast(setarr); |
|
|
|
|
|
const length = array.push(key); |
|
|
return (indexes[key] = length - 1); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function pop<T extends Key>(setarr: SetArray<T>): void { |
|
|
const { array, _indexes: indexes } = cast(setarr); |
|
|
if (array.length === 0) return; |
|
|
|
|
|
const last = array.pop()!; |
|
|
indexes[last] = undefined; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function remove<T extends Key>(setarr: SetArray<T>, key: T): void { |
|
|
const index = get(setarr, key); |
|
|
if (index === undefined) return; |
|
|
|
|
|
const { array, _indexes: indexes } = cast(setarr); |
|
|
for (let i = index + 1; i < array.length; i++) { |
|
|
const k = array[i]; |
|
|
array[i - 1] = k; |
|
|
indexes[k]!--; |
|
|
} |
|
|
indexes[key] = undefined; |
|
|
array.pop(); |
|
|
} |
|
|
|