Skip to content

Instantly share code, notes, and snippets.

@humodz
Last active August 19, 2022 12:13
Show Gist options
  • Save humodz/db32d80978262b5fb53a261ee77efbab to your computer and use it in GitHub Desktop.
Save humodz/db32d80978262b5fb53a261ee77efbab to your computer and use it in GitHub Desktop.
JS and TS utilities
JS and TS utilities
export function unique<T>(items: Iterable<T>): T[] {
return [...new Set(items)];
}
export function reversed<T>(items: Iterable<T>): T[] {
return [...items].reverse();
}
export function last<T>(items: T[]): T {
return items[items.length - 1];
}
export function range(begin: number, end: number): number[] {
return Array(end - begin).fill(begin).map((e, i) => e + i);
}
export function enumerate<T>(items: Iterable<T>): Array<[number, T]> {
return Array.from(items, (it, i) => [i, it]);
}
const $ = (s, e = document) => e.querySelector(s);
const $$ = (s, e = document) => [...e.querySelectorAll(s)];
function copy(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.top = '0';
textArea.style.left = '0';
textArea.style.position = 'fixed';
document.body.appendChild(textArea);
try {
textArea.focus();
textArea.select();
document.execCommand('copy');
} finally {
document.body.removeChild(textArea);
}
}
function save(filename, data) {
const blob = new Blob([data], { type: 'text' });
const elem = document.createElement('a');
elem.href = URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem);
try {
elem.click();
} finally {
document.body.removeChild(elem);
}
}
const identity = (item: any) => item;
export function groupByIntoRecord<Item, Key extends string | number | symbol, Value = Item>(
items: Iterable<Item>,
keyFn: (item: Item) => Key,
valueFn: (item: Item) => Value = identity
): Record<Key, Value[]> {
const result: Record<Key, Value[]> = {} as any;
for (const item of items) {
const key = keyFn(item);
const value = valueFn(item);
result[key] = result[key] || [];
result[key].push(value);
}
return result;
}
export function groupByIntoMap<Item, Key, Value = Item>(
items: Iterable<Item>,
keyFn: (item: Item) => Key,
valueFn: (item: Item) => Value = identity
): Map<Key, Value[]> {
const result = new Map<Key, Value[]>();
for (const item of items) {
const key = keyFn(item);
const value = valueFn(item);
if (!result.has(key)) {
result.set(key, []);
}
result.get(key)!.push(value);
}
return result;
}
export function random(begin: number, end: number) {
return Math.random() * (end - begin) + begin;
}
export function randomInt(begin: number, end: number) {
return Math.floor(Math.random() * (end - begin)) + begin;
}
export function randomItem<T>(items: T[]) {
const i = randomInt(0, items.length);
return items[i];
}
export function shuffled<T>(items: Iterable<T>): T[] {
return shuffle([...items]);
}
export function shuffle<T>(items: T[]): T[] {
for (let i = 0; i < items.length; i++) {
const j = randomInt(i, items.length);
[items[i], items[j]] = [items[j], items[i]];
}
return items;
}
export type Compare<T> = (a: T, b: T) => number;
export const CompareTo = Symbol('CompareTo');
export const defaultCompare: Compare<any> = (a, b) => {
if (a && a[CompareTo]) {
return a[CompareTo](b);
} else if (b && b[CompareTo]) {
return -b[CompareTo](a);
} else if (Array.isArray(a) && Array.isArray(b)) {
return arrayCompare(a, b);
} else {
return simpleCompare(a, b);
}
}
export const simpleCompare: Compare<any> = (a, b) => {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
export const arrayCompare: Compare<any[]> = (a, b) => {
const length = Math.min(a.length, b.length);
for (let i = 0; i < length; i++) {
const sign = defaultCompare(a[i], b[i]);
if (sign !== 0) {
return sign;
}
}
return simpleCompare(a.length, b.length);
};
export function sorted<T>(
items: Iterable<T>,
compare: Compare<T> = defaultCompare
): T[] {
return [...items].sort(compare);
}
export function backwards<T>(compare: Compare<T> = defaultCompare): Compare<T> {
return (a, b) => -compare(a, b);
}
export function by<T>(keyFn: (it: T) => unknown, compare: Compare<unknown> = defaultCompare): Compare<T> {
return (a, b) => {
const keyA = keyFn(a);
const keyB = keyFn(b);
return compare(keyA, keyB);
};
}
export function descending(value: unknown, compare = defaultCompare): unknown {
return {
[CompareTo]: (other: unknown) => -compare(value, other)
};
}
export function removeDiacritics(text: string): string {
return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
// node.js only
export function toBase64(text: string): string {
return Buffer.from(text).toString('base64');
}
// node.js only
export function fromBase64(base64: string): string {
return Buffer.from(base64, 'base64').toString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment