Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 1x 27x 28x 49x 27x 27x 27x 1x 4x 1x 1x 1x 9x 1x 5x 1x 11x 2x 9x 4x 5x 36x 9x 9x 1x 72x 120x 120x 2x 118x 118x 55x 55x 63x 38x 38x 25x 1x | export interface Options<K> { keys?: K[]; // only these keys will be transposed } type TransposedValues<T, K extends keyof T> = { [V in T[K] extends string | number | symbol ? T[K] : never]: T[] | undefined; }; export type Transposed<T, K extends keyof T> = { [Key in keyof T]: TransposedValues<T, K>; }; /** * If T is not never, use T. Otherwise, infer the type from the keys K */ type InferType<T, K extends keyof any> = [T] extends [never] ? [K] extends [never] ? any : { [Key in K]: any } & { [Key in string | number | symbol]: any } : T; export class OatyArray<T = never, K extends keyof T = keyof T> { private _transposed = {} as Transposed<InferType<T, K>, K>; private _data: InferType<T, K>[]; private _options: Options<K>; constructor( data: readonly InferType<T, K>[] = [], options: Options<K> = {} ) { this._data = [...data]; this._options = options; this.transpose(this._data); } get keys(): K[] { return (this._options.keys ?? Object.keys(this._transposed)) as K[] } get length(): number { return this._data.length } get data(): InferType<T, K>[] { return this._data } get transposed(): Transposed<InferType<T, K>, K> { return this._transposed } public get<KN extends K>(keyName: KN): TransposedValues<InferType<T, K>, KN>; public get<KN extends K>(keyName: KN, keyValue: InferType<T, K>[KN]): InferType<T, K>[] | undefined; public get<KN extends K>( keyName: KN, keyValue?: InferType<T, K>[KN] ): TransposedValues<InferType<T, K>, KN> | InferType<T, K>[] | undefined { if (this._transposed[keyName] === undefined) { throw new ReferenceError(`The key '${keyName}' has not been transposed`) } if (keyValue === undefined) { return this._transposed[keyName] } return this._transposed[keyName][keyValue as keyof TransposedValues<InferType<T, K>, KN>] } public push(...data: readonly InferType<T, K>[]) { this.transpose(data) return this._data.push(...data) } private transpose(data: readonly InferType<T, K>[]) { for (const datum of data) { for (const key of (this._options.keys ?? Object.keys(datum) as (keyof typeof datum)[])) { if (datum[key] === undefined) { continue } const searchKey = datum[key] as keyof TransposedValues<InferType<T, K>, K>; if (this._transposed[key] === undefined) { this._transposed[key] = { [searchKey]: [datum] } as TransposedValues<InferType<T, K>, K> continue } if (this._transposed[key][searchKey] === undefined) { this._transposed[key][searchKey] = [datum] continue } this._transposed[key][searchKey]!.push(datum) } } } } |