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