Skip to content

Instantly share code, notes, and snippets.

@jRimbault
Last active April 18, 2021 11:24
Show Gist options
  • Save jRimbault/6bab296da92a757fd42785cb0366f993 to your computer and use it in GitHub Desktop.
Save jRimbault/6bab296da92a757fd42785cb0366f993 to your computer and use it in GitHub Desktop.
function partition<T, K extends string | number>(
list: readonly T[],
getKey: (el: T) => K,
) {
const res: { [k in K]?: T[] } = {}
for (const el of list) {
const key = getKey(el)
const target: T[] = res[key] ?? (res[key] = [])
target.push(el)
}
return res
}
function mapObject<K extends string, T, U>(
record: { [k in K]: T },
mapper: (value: T) => U,
) {
const result = {} as { [k in K]: U }
for (const key in record) {
result[key] = mapper(record[key])
}
return result
}
function toMap<Key, Value>(list: readonly Value[], toKey: (v: Value) => Key): Map<Key, Value> {
// return new Map(list.map(el => [toKey(el), el])); // O(2n)
const map = new Map<Key, Value>()
for (const el of list) {
map.set(toKey(el), el)
}
return map // O(n)
}
type ComparableKeys<T> = {
[K in keyof T]: T[K] extends string | number ? K : never;
}[keyof T];
function sortBy<
T,
K extends ComparableKeys<T>,
R extends string | number,
>(selector: K | ((item: T) => R), reverse = false) {
const order = reverse ? -1 : 1;
function cmp<V extends T[K] | R>(a: V, b: V) {
return order * (a > b ? 1 : a < b ? -1 : 0);
}
if (selector instanceof Function) {
return (a: T, b: T) => cmp(selector(a), selector(b));
}
return (a: T, b: T) => cmp(a[selector], b[selector]);
}
// https://github.com/microsoft/TypeScript/issues/13923
export type SubType<T, Condition> = Pick<
T,
{
[K in keyof T]: T[K] extends Condition ? K : never;
}[keyof T]
>;
export type SubTypeInverse<T, Condition> = Omit<T, keyof SubType<T, Condition>>;
export type Writable<T> = { -readonly [P in keyof T]-?: T[P] }; // only use in unit tests setup
export type ChangeKeyType<T, K extends keyof T, U> = Omit<T, K> & { [k in K]?: U };
export type Override<What, With> = Omit<What, keyof With> & With;
export type Dictionary<K extends string, T> = Partial<Record<K, T>>;
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends Array<infer U>
? Array<DeepPartial<U>>
: T[P] extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: DeepPartial<T[P]>;
};
type ZipRow<T extends unknown[][]> = {
[P in keyof T]: T[P] extends (infer U)[] ? U : never
}
function zip<T extends unknown[][]>(...lists: T) {
const [list = [], ...rest] = lists
return list.map((el, i) => [el, ...rest.map(l => l[i])] as ZipRow<T>)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment