this repo has no description
1import type { Option } from "./option.ts"; 2 3export function first<T>(arr: readonly T[]): Option<T> { 4 return arr[0] ?? null; 5} 6 7export function last<T>(arr: readonly T[]): Option<T> { 8 return arr[arr.length - 1] ?? null; 9} 10 11export function at<T>(arr: readonly T[], index: number): Option<T> { 12 if (index < 0) index = arr.length + index; 13 return arr[index] ?? null; 14} 15 16export function find<T>( 17 arr: readonly T[], 18 predicate: (t: T) => boolean, 19): Option<T> { 20 return arr.find(predicate) ?? null; 21} 22 23export function findMap<T, U>( 24 arr: readonly T[], 25 fn: (t: T) => Option<U>, 26): Option<U> { 27 for (const item of arr) { 28 const result = fn(item); 29 if (result != null) return result; 30 } 31 return null; 32} 33 34export function findIndex<T>( 35 arr: readonly T[], 36 predicate: (t: T) => boolean, 37): Option<number> { 38 const index = arr.findIndex(predicate); 39 return index >= 0 ? index : null; 40} 41 42export function partition<T>( 43 arr: readonly T[], 44 predicate: (t: T) => boolean, 45): [T[], T[]] { 46 const pass: T[] = []; 47 const fail: T[] = []; 48 for (const item of arr) { 49 if (predicate(item)) { 50 pass.push(item); 51 } else { 52 fail.push(item); 53 } 54 } 55 return [pass, fail]; 56} 57 58export function groupBy<T, K extends string | number>( 59 arr: readonly T[], 60 keyFn: (t: T) => K, 61): Record<K, T[]> { 62 const result = {} as Record<K, T[]>; 63 for (const item of arr) { 64 const key = keyFn(item); 65 if (!result[key]) { 66 result[key] = []; 67 } 68 result[key].push(item); 69 } 70 return result; 71} 72 73export function unique<T>(arr: readonly T[]): T[] { 74 return [...new Set(arr)]; 75} 76 77export function uniqueBy<T, K>(arr: readonly T[], keyFn: (t: T) => K): T[] { 78 const seen = new Set<K>(); 79 const result: T[] = []; 80 for (const item of arr) { 81 const key = keyFn(item); 82 if (!seen.has(key)) { 83 seen.add(key); 84 result.push(item); 85 } 86 } 87 return result; 88} 89 90export function sortBy<T>( 91 arr: readonly T[], 92 keyFn: (t: T) => number | string, 93): T[] { 94 return [...arr].sort((a, b) => { 95 const ka = keyFn(a); 96 const kb = keyFn(b); 97 if (ka < kb) return -1; 98 if (ka > kb) return 1; 99 return 0; 100 }); 101} 102 103export function sortByDesc<T>( 104 arr: readonly T[], 105 keyFn: (t: T) => number | string, 106): T[] { 107 return [...arr].sort((a, b) => { 108 const ka = keyFn(a); 109 const kb = keyFn(b); 110 if (ka > kb) return -1; 111 if (ka < kb) return 1; 112 return 0; 113 }); 114} 115 116export function chunk<T>(arr: readonly T[], size: number): T[][] { 117 const result: T[][] = []; 118 for (let i = 0; i < arr.length; i += size) { 119 result.push(arr.slice(i, i + size)); 120 } 121 return result; 122} 123 124export function zip<T, U>(a: readonly T[], b: readonly U[]): [T, U][] { 125 const length = Math.min(a.length, b.length); 126 const result: [T, U][] = []; 127 for (let i = 0; i < length; i++) { 128 result.push([a[i], b[i]]); 129 } 130 return result; 131} 132 133export function zipWith<T, U, R>( 134 a: readonly T[], 135 b: readonly U[], 136 fn: (t: T, u: U) => R, 137): R[] { 138 const length = Math.min(a.length, b.length); 139 const result: R[] = []; 140 for (let i = 0; i < length; i++) { 141 result.push(fn(a[i], b[i])); 142 } 143 return result; 144} 145 146export function intersperse<T>(arr: readonly T[], separator: T): T[] { 147 if (arr.length <= 1) return [...arr]; 148 const result: T[] = [arr[0]]; 149 for (let i = 1; i < arr.length; i++) { 150 result.push(separator, arr[i]); 151 } 152 return result; 153} 154 155export function range(start: number, end: number): number[] { 156 const result: number[] = []; 157 for (let i = start; i < end; i++) { 158 result.push(i); 159 } 160 return result; 161} 162 163export function isEmpty<T>(arr: readonly T[]): boolean { 164 return arr.length === 0; 165} 166 167export function isNonEmpty<T>(arr: readonly T[]): arr is [T, ...T[]] { 168 return arr.length > 0; 169} 170 171export function sum(arr: readonly number[]): number { 172 return arr.reduce((acc, n) => acc + n, 0); 173} 174 175export function sumBy<T>(arr: readonly T[], fn: (t: T) => number): number { 176 return arr.reduce((acc, t) => acc + fn(t), 0); 177} 178 179export function maxBy<T>(arr: readonly T[], fn: (t: T) => number): Option<T> { 180 if (arr.length === 0) return null; 181 let max = arr[0]; 182 let maxValue = fn(max); 183 for (let i = 1; i < arr.length; i++) { 184 const value = fn(arr[i]); 185 if (value > maxValue) { 186 max = arr[i]; 187 maxValue = value; 188 } 189 } 190 return max; 191} 192 193export function minBy<T>(arr: readonly T[], fn: (t: T) => number): Option<T> { 194 if (arr.length === 0) return null; 195 let min = arr[0]; 196 let minValue = fn(min); 197 for (let i = 1; i < arr.length; i++) { 198 const value = fn(arr[i]); 199 if (value < minValue) { 200 min = arr[i]; 201 minValue = value; 202 } 203 } 204 return min; 205}