Created
December 14, 2023 17:15
-
-
Save itsMapleLeaf/eeed3cbfe07387e7761d79419406f44c to your computer and use it in GitHub Desktop.
extended iterable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { Truthy } from "./types.ts" | |
class ExtendedIterable<T> implements Iterable<T> { | |
constructor(private iterable: Iterable<T>) {} | |
*[Symbol.iterator]() { | |
yield* this.iterable | |
} | |
apply<U>(fn: (iterable: ExtendedIterable<T>) => Iterable<U>) { | |
return new ExtendedIterable(fn(this)) | |
} | |
map<U>(mapper: (value: T) => U) { | |
return this.apply(function* (iterable: ExtendedIterable<T>) { | |
for (const value of iterable) { | |
yield mapper(value) | |
} | |
}) | |
} | |
filter(filter: BooleanConstructor): ExtendedIterable<Truthy<T>> | |
filter<U extends T>(filter: (value: T) => value is U): ExtendedIterable<U> | |
filter(filter: (value: T) => boolean) { | |
return this.apply(function* (iterable: ExtendedIterable<T>) { | |
for (const value of iterable) { | |
if (filter(value)) yield value | |
} | |
}) | |
} | |
reduce<U>(reducer: (accumulator: U, value: T) => U, initialValue: U) { | |
let result = initialValue | |
for (const value of this.iterable) { | |
result = reducer(result, value) | |
} | |
return result | |
} | |
array() { | |
return [...this.iterable] | |
} | |
unique() { | |
return this.apply(function* (iterable: ExtendedIterable<T>) { | |
const seen = new Set<T>() | |
for (const value of iterable) { | |
if (!seen.has(value)) { | |
seen.add(value) | |
yield value | |
} | |
} | |
}) | |
} | |
first() { | |
const iterable = this[Symbol.iterator]().next() | |
return iterable.done ? undefined : iterable.value | |
} | |
} | |
export type { ExtendedIterable } | |
/** Helper to wrap an iterator with useful methods */ | |
export function it<T>(iterable: Iterable<T>) { | |
return new ExtendedIterable(iterable) | |
} | |
it.objectEntries = function objectEntries<T>(obj: Record<string, T>) { | |
return it(Object.entries(obj)) | |
} | |
it.factory = function factory<Args extends unknown[], Return>( | |
fn: (...args: Args) => Iterable<Return>, | |
) { | |
return (...args: Args) => new ExtendedIterable(fn(...args)) | |
} | |
it.promise = { | |
all: <T>(fn: () => Iterable<T | PromiseLike<T>>) => Promise.all(fn()), | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment