Skip to content

Commit

Permalink
chore: format
Browse files Browse the repository at this point in the history
  • Loading branch information
aleclarson committed Jul 2, 2024
1 parent 0bfd3d2 commit d052f2e
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 1 deletion.
239 changes: 239 additions & 0 deletions 0001-feat-array-support-iterables-in-some-array-functions.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
From 87c38ee9537a269cc3f8fe4da7990291f9edad0e Mon Sep 17 00:00:00 2001
From: Alec Larson <1925840+aleclarson@users.noreply.github.com>
Date: Sat, 22 Jun 2024 14:34:09 -0400
Subject: [PATCH] feat(array): support iterables in some array functions

---
src/array.ts | 115 +++++++++++++++++++++++++++++++++++----------------
1 file changed, 80 insertions(+), 35 deletions(-)

diff --git a/src/array.ts b/src/array.ts
index c7e70d4..f7e9cd9 100644
--- a/src/array.ts
+++ b/src/array.ts
@@ -6,10 +6,10 @@ import { isArray, isFunction } from './typed'
* each item in that group.
*/
export const group = <T, Key extends string | number | symbol>(
- array: readonly T[],
+ array: Iterable<T>,
getGroupId: (item: T) => Key
): Partial<Record<Key, T[]>> => {
- return array.reduce((acc, item) => {
+ return reduce(array, (acc, item) => {
const groupId = getGroupId(item)
if (!acc[groupId]) acc[groupId] = []
acc[groupId].push(item)
@@ -58,10 +58,10 @@ export function zip<T>(...arrays: T[][]): T[][] {
* Ex. const zipped = zipToObject(['a', 'b'], 1) // { a: 1, b: 1 }
*/
export function zipToObject<K extends string | number | symbol, V>(
- keys: K[],
+ keys: Iterable<K>,
values: V | ((key: K, idx: number) => V) | V[]
): Record<K, V> {
- if (!keys.length) {
+ if (isEmpty(keys)) {
return {} as Record<K, V>
}

@@ -71,7 +71,7 @@ export function zipToObject<K extends string | number | symbol, V>(
? (_k: K, i: number) => values[i]
: (_k: K, _i: number) => values

- return keys.reduce((acc, key, idx) => {
+ return reduce(keys, (acc, key, idx) => {
acc[key] = getValue(key, idx)
return acc
}, {} as Record<K, V>)
@@ -82,30 +82,37 @@ export function zipToObject<K extends string | number | symbol, V>(
* and comparing with the second. Keep the one you want then
* compare that to the next item in the list with the same
*
- * Ex. const greatest = () => boil(numbers, (a, b) => a > b)
+ * Ex. const greatest = () => boil(numbers, (a, b) => a > b ? a : b)
*/
-export const boil = <T>(
- array: readonly T[],
+export function boil<T>(array: readonly [T, ...T[]], compareFunc: (a: T, b: T) => T): T
+export function boil<T>(array: Iterable<T>, compareFunc: (a: T, b: T) => T): T | null
+export function boil <T>(
+ array: Iterable<T>,
compareFunc: (a: T, b: T) => T
-) => {
- if (!array || (array.length ?? 0) === 0) return null
- return array.reduce(compareFunc)
+) {
+ if (isEmpty(array)) return null
+ let acc!: T, i = 0
+ for (const item of array) {
+ acc = i++ === 0 ? item : compareFunc(acc, item)
+ }
+ return acc
}

/**
* Sum all numbers in an array. Optionally provide a function
* to convert objects in the array to number values.
*/
-export function sum<T extends number>(array: readonly T[]): number
-export function sum<T extends object>(
- array: readonly T[],
- fn: (item: T) => number
+export function sum<T extends number>(array: Iterable<T>): number
+export function sum<T>(
+ array: Iterable<T>,
+ getter: (item: T) => number
): number
-export function sum<T extends object | number>(
- array: readonly any[],
- fn?: (item: T) => number
+export function sum<T>(
+ array: Iterable<any>,
+ getter?: (item: T) => number
): number {
- return (array || []).reduce((acc, item) => acc + (fn ? fn(item) : item), 0)
+ const get = getter ?? ((v: any) => v)
+ return reduce(array, (acc, item) => acc + get(item), 0)
}

/**
@@ -160,10 +167,10 @@ export const alphabetical = <T>(
}

export const counting = <T, TId extends string | number | symbol>(
- list: readonly T[],
+ list: Iterable<T>,
identity: (item: T) => TId
): Record<TId, number> => {
- return list.reduce((acc, item) => {
+ return reduce(list, (acc, item) => {
const id = identity(item)
acc[id] = (acc[id] ?? 0) + 1
return acc
@@ -198,11 +205,11 @@ export const replace = <T>(
* into a dictionary key & value
*/
export const objectify = <T, Key extends string | number | symbol, Value = T>(
- array: readonly T[],
+ array: Iterable<T>,
getKey: (item: T) => Key,
getValue: (item: T) => Value = item => item as unknown as Value
): Record<Key, Value> => {
- return array.reduce((acc, item) => {
+ return reduce(array, (acc, item) => {
acc[getKey(item)] = getValue(item)
return acc
}, {} as Record<Key, Value>)
@@ -216,11 +223,11 @@ export const objectify = <T, Key extends string | number | symbol, Value = T>(
* select([1, 2, 3, 4], x => x*x, x > 2) == [9, 16]
*/
export const select = <T, K>(
- array: readonly T[],
+ array: Iterable<T>,
mapper: (item: T, index: number) => K,
condition: (item: T, index: number) => boolean
) => {
- return array.reduce((acc, item, index) => {
+ return reduce(array, (acc, item, index) => {
if (!condition(item, index)) return acc
acc.push(mapper(item, index))
return acc
@@ -235,15 +242,19 @@ export const select = <T, K>(
* max([{ num: 1 }, { num: 2 }], x => x.num) == { num: 2 }
*/
export function max(array: readonly [number, ...number[]]): number
-export function max(array: readonly number[]): number | null
+export function max(array: Iterable<number>): number | null
export function max<T>(
- array: readonly T[],
+ array: readonly [T, ...T[]],
+ getter: (item: T) => number
+): T
+export function max<T>(
+ array: Iterable<T>,
getter: (item: T) => number
): T | null
export function max<T>(
- array: readonly T[],
+ array: Iterable<T>,
getter?: (item: T) => number
-): T | null {
+) {
const get = getter ?? ((v: any) => v)
return boil(array, (a, b) => (get(a) > get(b) ? a : b))
}
@@ -256,15 +267,19 @@ export function max<T>(
* min([{ num: 1 }, { num: 2 }], x => x.num) == { num: 1 }
*/
export function min(array: readonly [number, ...number[]]): number
-export function min(array: readonly number[]): number | null
+export function min(array: Iterable<number>): number | null
export function min<T>(
- array: readonly T[],
+ array: readonly [T, ...T[]],
+ getter: (item: T) => number
+): T
+export function min<T>(
+ array: Iterable<T>,
getter: (item: T) => number
): T | null
export function min<T>(
- array: readonly T[],
+ array: Iterable<T>,
getter?: (item: T) => number
-): T | null {
+) {
const get = getter ?? ((v: any) => v)
return boil(array, (a, b) => (get(a) < get(b) ? a : b))
}
@@ -288,10 +303,10 @@ export const cluster = <T>(list: readonly T[], size: number = 2): T[][] => {
* value
*/
export const unique = <T, K extends string | number | symbol>(
- array: readonly T[],
+ array: Iterable<T>,
toKey?: (item: T) => K
): T[] => {
- const valueMap = array.reduce((acc, item) => {
+ const valueMap = reduce(array, (acc, item) => {
const key = toKey ? toKey(item) : (item as any as string | number | symbol)
if (acc[key]) return acc
acc[key] = item
@@ -534,3 +549,33 @@ export function shift<T>(arr: Array<T>, n: number) {

return [...arr.slice(-shiftNumber, arr.length), ...arr.slice(0, -shiftNumber)]
}
+
+function reduce<T, K>(
+ iterable: Iterable<T>,
+ reducer: (acc: K | undefined, item: T, index: number) => K,
+): K
+function reduce<T, K>(
+ iterable: Iterable<T>,
+ reducer: (acc: K, item: T, index: number) => K,
+ initial: K
+): K
+function reduce<T, K>(
+ iterable: Iterable<T>,
+ reducer: (acc: K | undefined, item: T, index: number) => K,
+ initial?: K,
+) {
+ let acc = initial
+ let index = 0
+ for (const item of iterable) {
+ acc = reducer(acc, item, index)
+ index++
+ }
+ return acc
+}
+
+
+function isEmpty(iterable: Iterable<any> | readonly any[]) {
+ if (isArray(iterable)) return !iterable.length
+ for (const _ of iterable) return false
+ return true
+}
--
2.41.0

2 changes: 1 addition & 1 deletion src/array/replaceOrAppend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function replaceOrAppend<T>(
const out = array.slice()
for (let index = 0; index < array.length; index++) {
if (match(array[index], index)) {
out[index] = newItem;
out[index] = newItem
return out
}
}
Expand Down

0 comments on commit d052f2e

Please sign in to comment.