UNPKG

@daiso-tech/core

Version:

The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.

1,469 lines 70.1 kB
/** * @module Collection */ import type { Comparator, PredicateInvokable, ForEach, Map, Modifier, Tap, Transform, Reduce, CrossJoinResult, EnsureMap, EnsureRecord } from "../../collection/contracts/_shared/_module.js"; import type { ISerializable } from "../../serde/contracts/_module-exports.js"; import type { Lazyable } from "../../utilities/_module-exports.js"; export type Collapse<TValue> = TValue extends Array<infer TItem> | Iterable<infer TItem> | ICollection<infer TItem> ? TItem : TValue; /** * The `ICollection` contract offers a fluent and efficient approach to working with {@link Iterable | `Iterable`} objects. * `ICollection` is immutable. * * IMPORT_PATH: `"@daiso-tech/core/collection/contracts"` * @group Contracts * @throws {UnexpectedCollectionError} {@link UnexpectedCollectionError} */ export type ICollection<TInput = unknown> = Iterable<TInput> & ISerializable<TInput[]> & { /** * The `toIterator` method converts the collection to a new iterator. */ toIterator(): Iterator<TInput, void>; /** * The `entries` returns an ICollection of key, value pairs for every entry in the collection. */ entries(): ICollection<[number, TInput]>; /** * The `keys` method returns an ICollection of keys in the collection. */ keys(): ICollection<number>; /** * The `values` method returns a copy of the collection. */ values(): ICollection<TInput>; /** * The `filter` method filters the collection using `predicateFn`, keeping only those items that pass `predicateFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5, 6]) * .filter(item => 2 < item && item < 5) * .toArray(); * // [3, 4] * } * ``` */ filter<TOutput extends TInput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>, TOutput>): ICollection<TOutput>; /** * The `reject` method filters the collection using `predicateFn`, keeping only those items that not pass `predicateFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5, 6]) * .reject(item => 2 < item && item < 5) * .toArray(); * // [1, 2, 5, 6] * } * ``` */ reject<TOutput extends TInput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>, TOutput>): ICollection<Exclude<TInput, TOutput>>; /** * The `map` method iterates through the collection and passes each item to `mapFn`. * The `mapFn` is free to modify the item and return it, thus forming a new collection of modified items. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5]) * .map(item => item * 2) * .toArray(); * // [2, 4, 6, 8, 10] * } * ``` */ map<TOutput>(mapFn: Map<TInput, ICollection<TInput>, TOutput>): ICollection<TOutput>; /** * The `reduce` method executes ` reduceFn ` function on each item of the array, passing in the return value from the calculation on the preceding item. * The final result of running the reducer across all items of the array is a single value. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3]); * .reduce((sum, item) => sum + item); * // 6 * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .append(["a", "b", "c"]) * .entries() * .reduce( * (record, [key, value]) => ({ * ...record, * [key]: value * }), * {} as Record<number, string> * ); * // { 0: "a", 1: "b", 2: "c" } * } * ``` */ reduce(reduceFn: Reduce<TInput, ICollection<TInput>, TInput>): TInput; reduce(reduceFn: Reduce<TInput, ICollection<TInput>, TInput>, initialValue: TInput): TInput; reduce<TOutput>(reduceFn: Reduce<TInput, ICollection<TInput>, TOutput>, initialValue: TOutput): TOutput; /** * The `join` method joins the collection's items with ` separator `. An error will be thrown when if a none string item is encounterd. * @throws {TypeCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4]) * .map(item => item.toString()) * .join(); * // "1,2,3,4" * } * ``` * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4]) * .map(item => item.toString()) * .join("_"); * // "1_2_3_4" * } * ``` */ join(separator?: string): Extract<TInput, string>; /** * The `collapse` method collapses a collection of iterables into a single, flat collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number[]>): void { * collection * .append([[1, 2], [3, 4]]) * .collapse() * .toArray(); * // [1, 2, 3, 4] * } * ``` */ collapse(): ICollection<Collapse<TInput>>; /** * The `flatMap` method returns a new array formed by applying `mapFn` to each item of the array, and then collapses the result by one level. * It is identical to a `map` method followed by a `collapse` method. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string[]>): void { * collection * .append([["a", "b"], ["c", "d"]]) * .flatMap(item => [item.length, ...item]) * .toArray(); * // [2, "a", "b", 2, "c", "d"] * } * ``` */ flatMap<TOutput>(mapFn: Map<TInput, ICollection<TInput>, Iterable<TOutput>>): ICollection<TOutput>; /** * The `change` method changes only the items that passes `predicateFn` using `mapFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5]) * .change(item => item % 2 === 0, item => item * 2) * .toArray(); * // [1, 4, 3, 8, 5] * } * ``` */ change<TFilterOutput extends TInput, TMapOutput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>, TFilterOutput>, mapFn: Map<TFilterOutput, ICollection<TInput>, TMapOutput>): ICollection<TInput | TFilterOutput | TMapOutput>; /** * The `set` method changes a item by i>index` using `value`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5]) * .set(1, -1) * .toArray(); * // [1, -1, 3, 4, 5] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5]) * .set(1, (prevValue) => prevValue - 2) * .toArray(); * // [1, 0, 3, 4, 5] * } * ``` */ set(index: number, value: TInput | Map<TInput, ICollection<TInput>, TInput>): ICollection<TInput>; /** * The `get` method returns the item by index. If the item is not found null will returned. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection = collection.append([1, 4, 2, 8, -2]); * * // Will be 2 * collection.get(2); * * // Will be null * collection.get(5); * } * ``` */ get(index: number): TInput | null; /** * The `getOrFail` method returns the item by index. If the item is not found an error will be thrown. * @throws {ItemNotFoundCollectionError} {@link ItemNotFoundCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection = collection.append([1, 4, 2, 8, -2]); * * // Will be 2 * collection.getOrFail(2); * * // An error will thrown * collection.getOrFail(5); * } * ``` */ getOrFail(index: number): TInput; /** * The `page` method returns a new collection containing the items that would be present on ` page ` with custom ` pageSize `. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5, 6, 7, 8, 9]) * .page(2, 3) * .toArray() * // [4, 5, 6] * } * ``` */ page(page: number, pageSize: number): ICollection<TInput>; /** * The `sum` method returns the sum of all items in the collection. If the collection includes other than number items an error will be thrown. * If the collection is empty an error will also be thrown. * @throws {TypeCollectionError} {@link TypeCollectionError} * @throws {EmptyCollectionError} {@link EmptyCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3]) * .sum(); * // 6 * } * ``` */ sum(): Extract<TInput, number>; /** * The `average` method returns the average of all items in the collection. If the collection includes other than number items an error will be thrown. * If the collection is empty an error will also be thrown. * @throws {TypeCollectionError} {@link TypeCollectionError} * @throws {EmptyCollectionError} {@link EmptyCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3]) * .average() * // 2 * } * ``` */ average(): Extract<TInput, number>; /** * The `median` method returns the median of all items in the collection. If the collection includes other than number items an error will be thrown. * If the collection is empty an error will also be thrown. * @throws {TypeCollectionError} {@link TypeCollectionError} * @throws {EmptyCollectionError} {@link EmptyCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3]) * .median(); * // 2 * } * ``` */ median(): Extract<TInput, number>; /** * The `min` method returns the min of all items in the collection. If the collection includes other than number items an error will be thrown. * If the collection is empty an error will also be thrown. * @throws {TypeCollectionError} {@link TypeCollectionError} * @throws {EmptyCollectionError} {@link EmptyCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3]) * .min(); * // 1 * } * ``` */ min(): Extract<TInput, number>; /** * The `max` method returns the max of all items in the collection. If the collection includes other than number items an error will be thrown. * If the collection is empty an error will also be thrown. * @throws {TypeCollectionError} {@link TypeCollectionError} * @throws {EmptyCollectionError} {@link EmptyCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3]) * .max(); * // 3 * } * ``` */ max(): Extract<TInput, number>; /** * The `percentage` method may be used to quickly determine the percentage of items in the collection that pass `predicateFn`. * If the collection is empty an error will also be thrown. * @throws {EmptyCollectionError} {@link EmptyCollectionError} * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 1, 2, 2, 2, 3]) * .percentage(value => value === 1); * // 33.333 * } * ``` */ percentage(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): number; /** * The `some` method determines whether at least one item in the collection matches `predicateFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([0, 1, 2, 3, 4, 5]) * .some(item => item === 1); * // true * } * ``` */ some<TOutput extends TInput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>, TOutput>): boolean; /** * The `every` method determines whether all items in the collection matches `predicateFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([0, 1, 2, 3, 4, 5]) * .every(item => item < 6); * // true * } * ``` */ every<TOutput extends TInput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>, TOutput>): boolean; /** * The `take` method takes the first `limit` items. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([0, 1, 2, 3, 4, 5]) * .take(3) * .toArray(); * // [0, 1, 2] * } * ``` * * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([0, 1, 2, 3, 4, 5]) * .take(-2) * .toArray(); * // [0, 1, 2, 3] * } * ``` */ take(limit: number): ICollection<TInput>; /** * The `takeUntil` method takes items until `predicateFn` returns true. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4]) * .takeUntil(item => item >= 3) * .toArray(); * // [1, 2] * } * ``` */ takeUntil(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): ICollection<TInput>; /** * The `takeWhile` method takes items until `predicateFn` returns false. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4]) * .takeWhile(item => item < 4) * .toArray(); * // [1, 2, 3] * } * ``` */ takeWhile(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): ICollection<TInput>; /** * The `skip` method skips the first `offset` items. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .append([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) * .skip(4) * .toArray(); * // [5, 6, 7, 8, 9, 10] * } * ``` */ skip(offset: number): ICollection<TInput>; /** * The `skipUntil` method skips items until `predicateFn` returns true. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4]) * .skipUntil(item => item >= 3) * .toArray(); * // [3, 4] * } * ``` */ skipUntil(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): ICollection<TInput>; /** * The `skipWhile` method skips items until `predicateFn` returns false. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4]) * .skipWhile(item => item <= 3) * .toArray(); * // [4] * } * ``` */ skipWhile(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): ICollection<TInput>; /** * The `when` method will execute `callback` when `condition` evaluates to true. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4]) * .when(true, collection => collection.append([-3])) * .when(false, collection => collection.append([20])) * .toArray(); * // [1, 2, 3, 4, -3] * } * ``` */ when<TExtended = TInput>(condition: boolean, callback: Modifier<ICollection<TInput>, ICollection<TExtended>>): ICollection<TInput | TExtended>; /** * The `whenEmpty` method will execute `callback` when the collection is empty. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([]) * .whenEmpty(collection => collection.append([-3])) * .toArray(); * // [-3] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1]) * .whenEmpty(collection => collection.append([-3])) * .toArray(); * // [1] * } * ``` */ whenEmpty<TExtended = TInput>(callback: Modifier<ICollection<TInput>, ICollection<TExtended>>): ICollection<TInput | TExtended>; /** * The `whenNot` method will execute `callback` when `condition` evaluates to false. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection.apppend([1, 2, 3, 4]) * .whenNot(true, collection => collection.append([-3])) * .whenNot(false, collection => collection.append([20])) * .toArray(); * // [1, 2, 3, 4, 20] * } * ``` */ whenNot<TExtended = TInput>(condition: boolean, callback: Modifier<ICollection<TInput>, ICollection<TExtended>>): ICollection<TInput | TExtended>; /** * The `whenNotEmpty` method will execute `callback` when the collection is not empty. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection.apppend([]) * .whenNotEmpty(collection => collection.append([-3])) * .toArray(); * // [] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection = collection * .apppend([1]) * .whenNotEmpty(collection => collection.append([-3])) * .toArray(); * // [1, -3] * } * ``` */ whenNotEmpty<TExtended = TInput>(callback: Modifier<ICollection<TInput>, ICollection<TExtended>>): ICollection<TInput | TExtended>; /** * The `pipe` method passes the orignal collection to `callback` and returns the result from `callback`. * This method is useful when you want compose multiple smaller functions. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * function toNbrs<TInput>( * collection: ICollection<TInput>, * ): ICollection<number> { * return collection * .map((item) => Number(item)) * .reject((nbr) => Number.isNaN(nbr)); * } * * function nbrToStr(collection: ICollection<number>): number[] { * return collection.repeat(2).toArray(); * } * * const piped = collection * .apppend([1, "2", "a", 1, 3, {}]) * .pipe(toNbrs) * .pipe(nbrToStr); * // [ 1, 2, 1, 3 ] * } * ``` */ pipe<TOutput = TInput>(callback: Transform<ICollection<TInput>, TOutput>): TOutput; /** * The `tap` method passes a copy of the original collection to `callback`, allowing you to do something with the items while not affecting the original collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection.apppend([1, 2, 3, 4, 5, 6]) * .tap(collection => { * collection * .filter(value => value % 2 === 0) * .forEach(value => console.log(value)) * }) * .toArray(); * // [1, 2, 3, 4, 5, 6] * } * ``` */ tap(callback: Tap<ICollection<TInput>>): ICollection<TInput>; /** * The `chunk` method breaks the collection into multiple, smaller collections of size `chunkSize`. * If `chunkSize` is not divisible with total number of items then the last chunk will contain the remaining items. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection.apppend([1, 2, 3, 4, 5, 6, 7]); * const chunks = collection.chunk(4); * chunks.map(chunk => chunk.toArray()).toArray(); * // [[1, 2, 3, 4], [5, 6, 7]] * } * ``` */ chunk(chunkSize: number): ICollection<ICollection<TInput>>; /** * The `chunkWhile` method breaks the collection into multiple, smaller collections based on the evaluation of `predicateFn`. * The chunk variable passed to the `predicateFn` may be used to inspect the previous item. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend("AABBCCCD") * .chunkWhile((value, index, chunk) => { * return value === chunk.last(); * }) * .map(chunk => chunk.toArray()) * .toArray(); * // [["A", "A"], ["B", "B"], ["C", "C", "C"], ["D"]] * } * ``` */ chunkWhile(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): ICollection<ICollection<TInput>>; /** * The `split` method breaks a collection evenly into `chunkAmount` of chunks. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5]) * .split(3) * .map(chunk => chunk.toArray()) * .toArray(); * // [[1, 2], [3, 4], [5]] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5, 6]) * .split(3) * .map(chunk => chunk.toArray()) * .toArray() * // [[1, 2], [3, 4], [5, 6]] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5, 6, 7]) * .split(3) * .map(chunk => chunk.toArray()) * .toArray(); * // [[1, 2, 7], [3, 4], [5, 6]] * } * ``` */ split(chunkAmount: number): ICollection<ICollection<TInput>>; /** * The `partition` method is used to separate items that pass `predicateFn` from those that do not. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5, 6]) * .partition(item => item < 3) * .map(chunk => chunk.toArray()) * .toArray(); * // [[1, 2], [3, 4, 5, 6]] * } * ``` */ partition(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>): ICollection<ICollection<TInput>>; /** * The `sliding` method returns a new collection of chunks representing a "sliding window" view of the items in the collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5]) * .sliding(2) * .map(chunk => chunk.toArray()) * .toArray(); * // [[1, 2], [2, 3], [3, 4], [4, 5]] * } * ``` */ sliding(chunkSize: number, step?: number): ICollection<ICollection<TInput>>; /** * The `groupBy` method groups the collection's items by ` selectFn `. * By default the equality check occurs on the item. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "a", "a", "b", "b", "c"]) * .groupBy() * .map(([key, collection]) => [key, .toArray()]) * .toArray(); * // [ * // [ * // "a", * // ["a", "a", "a"] * // ], * // [ * // "b", * // ["b", "b"] * // ], * // [ * // "c", * // ["c"] * // ] * // ] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection.apppend(["alice@gmail.com", "bob@yahoo.com", "carlos@gmail.com"]); * const group = collection * .groupBy(item => item.split("@")[1]) * .map(([key, collection]) => [key, .toArray()]) * .toArray(); * // [ * // [ * // "gmail.com", * // ["alice@gmail.com", "carlos@gmail.com"] * // ], * // [ * // "yahoo.com", * // ["bob@yahoo.com"] * // ] * // ] * } * ``` */ groupBy<TOutput = TInput>(selectFn?: Map<TInput, ICollection<TInput>, TOutput>): ICollection<[TOutput, ICollection<TInput>]>; /** * The `countBy` method counts the occurrences of values in the collection by ` selectFn `. * By default the equality check occurs on the item. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "a", "a", "b", "b", "c"]) * .countBy() * .map(([key, collection]) => [key, .toArray()]) * .toArray(); * // [ * // ["a", 3], * // ["b", 2], * // ["c", 1] * // ] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["alice@gmail.com", "bob@yahoo.com", "carlos@gmail.com"]) * .countBy(item => item.split("@")[1]) * .toArray(); * // [ * // ["gmail.com", 2], * // ["yahoo.com", 1] * // ] * } * ``` */ countBy<TOutput = TInput>(selectFn?: Map<TInput, ICollection<TInput>, TOutput>): ICollection<[TOutput, number]>; /** * The `unique` method removes all duplicate values from the collection by ` selectFn `. * By default the equality check occurs on the item. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 1, 2, 2, 3, 4, 2]) * .unique() * .toArray(); * // [1, 2, 3, 4] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * type Phone = { * name: string; * brand: string; * type: string; * }; * * // Assume the inputed collection is empty. * function main(collection: ICollection<Phone>): void { * collection * .apppend([ * { name: "iPhone 6", brand: "Apple", type: "phone" }, * { name: "iPhone 5", brand: "Apple", type: "phone" }, * { name: "Apple Watch", brand: "Apple", type: "watch" }, * { name: "Galaxy S6", brand: "Samsung", type: "phone" }, * { name: "Galaxy Gear", brand: "Samsung", type: "watch" }, * ]) * .unique(item => item.brand) * .toArray(); * // [ * // { name: "iPhone 6", brand: "Apple", type: "phone" }, * // { name: "Galaxy S6", brand: "Samsung", type: "phone" }, * // ] * } * ``` */ unique<TOutput = TInput>(selectFn?: Map<TInput, ICollection<TInput>, TOutput>): ICollection<TInput>; /** * The `difference` method will return the values in the original collection that are not present in `iterable`. * By default the equality check occurs on the item. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 2, 3, 4, 5]) * .difference([2, 4, 6, 8]) * .toArray(); * // [1, 3, 5] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * type Phone = { * name: string; * brand: string; * type: string; * }; * * // Assume the inputed collection is empty. * function main(collection: ICollection<Phone>): void { * collection * .apppend([ * { name: "iPhone 6", brand: "Apple", type: "phone" }, * { name: "iPhone 5", brand: "Apple", type: "phone" }, * { name: "Apple Watch", brand: "Apple", type: "watch" }, * { name: "Galaxy S6", brand: "Samsung", type: "phone" }, * { name: "Galaxy Gear", brand: "Samsung", type: "watch" }, * ]) * .difference( * [ * { name: "Apple Watch", brand: "Apple", type: "watch" }, * ], * (product) => product.type * ) * .toArray(); * // [ * // { name: "iPhone 6", brand: "Apple", type: "phone" }, * // { name: "iPhone 5", brand: "Apple", type: "phone" }, * // { name: "Galaxy S6", brand: "Samsung", type: "phone" }, * // ] * } * ``` */ difference<TOutput = TInput>(iterable: Iterable<TInput>, selectFn?: Map<TInput, ICollection<TInput>, TOutput>): ICollection<TInput>; /** * The `repeat` method will repeat the original collection `amount` times. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3]) * .repeat(3) * .toArray(); * // [1, 2, 3, 1, 2, 3, 1, 2, 3] * } * ``` */ repeat(amount: number): ICollection<TInput>; /** * The `padStart` method pads this collection with `fillItems` until the resulting collection size reaches `maxLength`. * The padding is applied from the start of this collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padStart(10, "foo") * .join(""); * // "foofoofabc" * } * ``` * @example * ```ts * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padStart(6, "123465") * .join(""); * // "123abc" * } * ``` * @example * ```ts * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padStart(8, "0") * .join(""); * // "00000abc" * } * ``` * @example * ```ts * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padStart(1, "_") * .join(""); * // "abc" * } * ``` */ padStart<TExtended = TInput>(maxLength: number, fillItems: Iterable<TExtended>): ICollection<TInput | TExtended>; /** * The `padEnd` method pads this collection with `fillItems` until the resulting collection size reaches `maxLength`. * The padding is applied from the end of this collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padEnd(10, "foo") * .join(""); * // "abcfoofoof" * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padEnd(6, "123465") * .join(""); * // "abc123" * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padEnd(8, "0") * .join(""); * // "abc00000" * * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .append("abc") * .padEnd(1, "_") * .join(""); * // "abc" * } * ``` */ padEnd<TExtended = TInput>(maxLength: number, fillItems: Iterable<TExtended>): ICollection<TInput | TExtended>; /** * The `slice` method creates porition of the original collection selected from `start` and `end` * where `start` and `end` (end not included) represent the index of items in the collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "b", "c", "d", "e", "f"]) * .slice(3) * .toArray(); * // ["d", "e", "f"] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "b", "c", "d", "e", "f"]) * .slice(undefined, 2) * .toArray() * // ["a", "b"] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "b", "c", "d", "e", "f"]) * .slice(2, 5) * .toArray() * // ["c", "d", "e"] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "b", "c", "d", "e", "f"]) * .slice(-2) * .toArray(); * // ["e", "f"] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "b", "c", "d", "e", "f"]) * .slice(undefined, -2) * .toArray() * // ["a", "b", "c", "d"] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["a", "b", "c", "d", "e", "f"]) * .slice(-4, -2) * .toArray(); * // ["c", "d"] * } * ``` */ slice(start?: number, end?: number): ICollection<TInput>; /** * The `prepend` method adds `iterable` to the beginning of the collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5]) * .prepend([-1, 20]) * .toArray(); * // [-1, 20, 1, 2, 3, 4, 5] * } * ``` */ prepend<TExtended = TInput>(iterable: Iterable<TInput | TExtended>): ICollection<TInput | TExtended>; /** * The `append` method adds `iterable` to the end of the collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4, 5]) * .append([-1, -2]) * .toArray(); * // [1, 2, 3, 4, 5, -1, -2,] * } * ``` */ append<TExtended = TInput>(iterable: Iterable<TInput | TExtended>): ICollection<TInput | TExtended>; /** * The `insertBefore` method adds `iterable` before the first item that matches `predicateFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 2, 3, 4, 5]) * .insertBefore(item => item === 2, [-1, 20]) * .toArray(); * // [1, -1, 20, 2, 2, 3, 4, 5] * } * ``` */ insertBefore<TExtended = TInput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>, iterable: Iterable<TInput | TExtended>): ICollection<TInput | TExtended>; /** * The `insertAfter` method adds `iterable` after the first item that matches `predicateFn`. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 2, 3, 4, 5]) * .insertAfter(item => item === 2, [-1, 20]) * .toArray(); * // [1, 2, -1, 20, 2, 3, 4, 5] * } * ``` */ insertAfter<TExtended = TInput>(predicateFn: PredicateInvokable<TInput, ICollection<TInput>>, iterable: Iterable<TInput | TExtended>): ICollection<TInput | TExtended>; /** * The `crossJoin` method cross joins the collection's values among `iterables`, returning a Cartesian product with all possible permutations. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2]) * .cross(["a", "b"]) * .toArray(); * // [ * // [1, "a"], * // [1, "b"], * // [2, "a"], * // [2, "b"], * // ] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2]) * .cross(["a", "b"]) * .cross(["I", "II"]) * .toArray(); * // [ * // [1, "a", "I"], * // [1, "a", "II"], * // [1, "b", "I"], * // [1, "b", "II"], * // [2, "a", "I"], * // [2, "a", "II"], * // [2, "b", "I"], * // [2, "b", "II"], * // ] * } * ``` */ crossJoin<TExtended>(iterable: Iterable<TExtended>): ICollection<CrossJoinResult<TInput, TExtended>>; /** * The `zip` method merges together the values of `iterable` with the values of the collection at their corresponding index. * The returned collection has size of the shortest collection. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["Chair", "Desk"]); * .zip([100, 200]); * .toArray(); * // [["Chair", 100], ["Desk", 200]] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["Chair", "Desk", "Couch"]) * .zip([100, 200]) * .toArray(); * // [["Chair", 100], ["Desk", 200]] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<string>): void { * collection * .apppend(["Chair", "Desk"]) * .zip([100, 200, 300]) * .toArray(); * // [["Chair", 100], ["Desk", 200]] * } * ``` */ zip<TExtended>(iterable: Iterable<TExtended>): ICollection<[TInput, TExtended]>; /** * The `sort` method sorts the collection. You can provide a `comparator` function. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([-1, 2, 4, 3]) * .sort() * .toArray() * // [-1, 2, 3, 4] * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * type Person = { * name: string; * age: number; * }; * * // Assume the inputed collection is empty. * function main(collection: ICollection<Person>): void { * collection * .apppend([ * { name: "Anders", age: 30 }, * { name: "Joe", age: 20 }, * { name: "Hasan", age: 25 }, * { name: "Linda", age: 19 } * ]) * .sort(({ age: ageA }, { age: ageB }) => ageA - ageB) * .toArray(); * // [ * // { name: "Linda", age: 19 } * // { name: "Joe", age: 20 }, * // { name: "Hasan", age: 25 }, * // { name: "Anders", age: 30 }, * // ] * } * ``` */ sort(comparator?: Comparator<TInput>): ICollection<TInput>; /** * The `reverse` method will reverse the order of the collection. * The reversing of the collection will be applied in chunks that are the size of ` chunkSize `. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([-1, 2, 4, 3]) * .reverse() * .toArray(); * // [3, 4, 2, -1] * } * ``` */ reverse(chunkSize?: number): ICollection<TInput>; /** * The `shuffle` method randomly shuffles the items in the collection. You can provide a custom Math.random function by passing in `mathRandom`. */ shuffle(mathRandom?: () => number): ICollection<TInput>; /** * The `first` method returns the first item in the collection that passes ` predicateFn `. * By default it will get the first item. If the collection is empty or no items passes ` predicateFn ` than null i returned. * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4]) * .first(); * // 1 * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume the inputed collection is empty. * function main(collection: ICollection<number>): void { * collection * .apppend([1, 2, 3, 4]) * .first(item => item > 2); * // 3 * } * ``` * @example * ```ts * import type { ICollection } from "@daiso-tech/core"; * * // Assume