diff --git a/package.json b/package.json index 4574d96..a5d09da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@infendro/collection", - "version": "0.0.2", + "version": "0.0.3", "scripts": { "build": "tsc" }, diff --git a/src/collection.ts b/src/collection.ts index a182381..61770a6 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -14,6 +14,9 @@ import {count} from "./collection/count"; import {distinct} from "./collection/distinct"; import {distinctBy} from "./collection/distinctBy"; import {drop} from "./collection/drop"; +import {dropLast} from "./collection/dropLast"; +import {dropLastUntil} from "./collection/dropLastUntil"; +import {dropLastWhile} from "./collection/dropLastWhile"; import {dropUntil} from "./collection/dropUntil"; import {dropWhile} from "./collection/dropWhile"; import {filter} from "./collection/filter"; @@ -69,24 +72,27 @@ import {sortedWith} from "./collection/sortedWith"; import {sum} from "./collection/sum"; import {sumBy} from "./collection/sumBy"; import {take} from "./collection/take"; +import {takeLast} from "./collection/takeLast"; +import {takeLastUntil} from "./collection/takeLastUntil"; +import {takeLastWhile} from "./collection/takeLastWhile"; import {takeUntil} from "./collection/takeUntil"; import {takeWhile} from "./collection/takeWhile"; import {toArray} from "./collection/toArray"; import {toMap} from "./collection/toMap"; +import {Key, Object, toObject} from "./collection/toObject"; import {toSet} from "./collection/toSet"; import {unzip} from "./collection/unzip"; import {windowed} from "./collection/windowed"; import {withIndex} from "./collection/withIndex"; import {zip} from "./collection/zip"; -import {Key, Object, toObject} from "./collection/toObject"; export type Collection = { [Symbol.iterator](): Iterator - toObject(this: Collection<[K, V]>): Object toArray(): T[] toSet(): Set toMap(this: Collection<[K, V]>): Map + toObject(this: Collection<[K, V]>): Object onEach(action: (it: T) => void): Collection forEach(action: (it: T) => void): void @@ -157,9 +163,15 @@ export type Collection = { drop(count: number): Collection dropWhile(predicate: (it: T) => boolean): Collection dropUntil(predicate: (it: T) => boolean): Collection + dropLast(count: number): Collection + dropLastWhile(predicate: (it: T) => boolean): Collection + dropLastUntil(predicate: (it: T) => boolean): Collection take(count: number): Collection takeWhile(predicate: (it: T) => boolean): Collection takeUntil(predicate: (it: T) => boolean): Collection + takeLast(count: number): Collection + takeLastWhile(predicate: (it: T) => boolean): Collection + takeLastUntil(predicate: (it: T) => boolean): Collection slice(start: number, end?: number): Collection map(transform: (it: T) => R): Collection @@ -192,9 +204,6 @@ function wrap(value: T[]): Collection { [Symbol.iterator]() { return value[Symbol.iterator](); }, - toObject() { - return toObject(value as [K, V][]); - }, toArray() { return toArray(value); }, @@ -204,6 +213,9 @@ function wrap(value: T[]): Collection { toMap() { return toMap(value as [K, V][]); }, + toObject() { + return toObject(value as [K, V][]); + }, onEach(action) { return wrap(onEach(value, action)); }, @@ -375,6 +387,15 @@ function wrap(value: T[]): Collection { dropUntil(predicate) { return wrap(dropUntil(value, predicate)); }, + dropLast(count) { + return wrap(dropLast(value, count)); + }, + dropLastWhile(predicate) { + return wrap(dropLastWhile(value, predicate)); + }, + dropLastUntil(predicate) { + return wrap(dropLastUntil(value, predicate)); + }, take(count) { return wrap(take(value, count)); }, @@ -384,6 +405,15 @@ function wrap(value: T[]): Collection { takeUntil(predicate) { return wrap(takeUntil(value, predicate)); }, + takeLast(count) { + return wrap(takeLast(value, count)); + }, + takeLastWhile(predicate) { + return wrap(takeLastWhile(value, predicate)); + }, + takeLastUntil(predicate) { + return wrap(takeLastUntil(value, predicate)); + }, slice(start, end) { return wrap(slice(value, start, end)); }, diff --git a/src/collection/dropLast.ts b/src/collection/dropLast.ts new file mode 100644 index 0000000..40678f5 --- /dev/null +++ b/src/collection/dropLast.ts @@ -0,0 +1,10 @@ +import {error} from "../util/error"; + +export function dropLast(value: T[], count: number): T[] { + if (count < 0) error(); + const result: T[] = []; + for (let i = 0; i < (value.length - count); i++) { + result.push(value[i]); + } + return result; +} diff --git a/src/collection/dropLastUntil.ts b/src/collection/dropLastUntil.ts new file mode 100644 index 0000000..b6da5ad --- /dev/null +++ b/src/collection/dropLastUntil.ts @@ -0,0 +1,11 @@ +export function dropLastUntil(value: T[], predicate: (it: T) => boolean): T[] { + let index = value.length - 1; + while (index >= 0 && !predicate(value[index])) { + index--; + } + const result: T[] = []; + for (let i = 0; i <= index; i++) { + result.push(value[i]); + } + return result; +} diff --git a/src/collection/dropLastWhile.ts b/src/collection/dropLastWhile.ts new file mode 100644 index 0000000..7f86664 --- /dev/null +++ b/src/collection/dropLastWhile.ts @@ -0,0 +1,11 @@ +export function dropLastWhile(value: T[], predicate: (it: T) => boolean): T[] { + let index = value.length - 1; + while (index >= 0 && predicate(value[index])) { + index--; + } + const result: T[] = []; + for (let i = 0; i <= index; i++) { + result.push(value[i]); + } + return result; +} diff --git a/src/collection/max.ts b/src/collection/max.ts index 8652d2e..e655a33 100644 --- a/src/collection/max.ts +++ b/src/collection/max.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function max(value: number[]): number { if (value.length === 0) error(); let max = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (it > max) max = it; } return max; diff --git a/src/collection/maxBy.ts b/src/collection/maxBy.ts index 78fb247..c0d0462 100644 --- a/src/collection/maxBy.ts +++ b/src/collection/maxBy.ts @@ -4,8 +4,8 @@ export function maxBy(value: T[], transform: (it: T) => number): T { if (value.length === 0) error(); let maxIt = value[0]; let maxVal = transform(maxIt); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val > maxVal) { maxIt = it; diff --git a/src/collection/maxByOrNull.ts b/src/collection/maxByOrNull.ts index 79b0fd6..61a6653 100644 --- a/src/collection/maxByOrNull.ts +++ b/src/collection/maxByOrNull.ts @@ -2,8 +2,8 @@ export function maxByOrNull(value: T[], transform: (it: T) => number): T | nu if (value.length === 0) return null; let maxIt = value[0]; let maxVal = transform(maxIt); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val > maxVal) { maxIt = it; diff --git a/src/collection/maxOf.ts b/src/collection/maxOf.ts index d795483..81cb746 100644 --- a/src/collection/maxOf.ts +++ b/src/collection/maxOf.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function maxOf(value: T[], transform: (it: T) => number): number { if (value.length === 0) error(); let max = transform(value[0]); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val > max) max = val; } diff --git a/src/collection/maxOfOrNull.ts b/src/collection/maxOfOrNull.ts index ddcbbc5..88b8291 100644 --- a/src/collection/maxOfOrNull.ts +++ b/src/collection/maxOfOrNull.ts @@ -1,8 +1,8 @@ export function maxOfOrNull(value: T[], transform: (it: T) => number): number | null { if (value.length === 0) return null; let max = transform(value[0]); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val > max) max = val; } diff --git a/src/collection/maxOrNull.ts b/src/collection/maxOrNull.ts index b3bb627..b5d4e72 100644 --- a/src/collection/maxOrNull.ts +++ b/src/collection/maxOrNull.ts @@ -1,8 +1,8 @@ export function maxOrNull(value: number[]): number | null { if (value.length === 0) return null; let max = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (it > max) max = it; } return max; diff --git a/src/collection/maxWith.ts b/src/collection/maxWith.ts index afeba58..0045b80 100644 --- a/src/collection/maxWith.ts +++ b/src/collection/maxWith.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function maxWith(value: T[], compare: (a: T, b: T) => number): T { if (value.length === 0) error(); let max = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (compare(it, max) > 0) max = it; } return max; diff --git a/src/collection/maxWithOrNull.ts b/src/collection/maxWithOrNull.ts index 035ef68..f39f365 100644 --- a/src/collection/maxWithOrNull.ts +++ b/src/collection/maxWithOrNull.ts @@ -1,8 +1,8 @@ export function maxWithOrNull(value: T[], compare: (a: T, b: T) => number): T | null { if (value.length === 0) return null; let max = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (compare(it, max) > 0) max = it; } return max; diff --git a/src/collection/min.ts b/src/collection/min.ts index 3f2da60..808dca8 100644 --- a/src/collection/min.ts +++ b/src/collection/min.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function min(value: number[]): number { if (value.length === 0) error(); let min = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (it < min) min = it; } return min; diff --git a/src/collection/minBy.ts b/src/collection/minBy.ts index e1bc728..5d106d9 100644 --- a/src/collection/minBy.ts +++ b/src/collection/minBy.ts @@ -4,8 +4,8 @@ export function minBy(value: T[], transform: (it: T) => number): T { if (value.length === 0) error(); let minIt = value[0]; let minVal = transform(minIt); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val < minVal) { minIt = it; diff --git a/src/collection/minByOrNull.ts b/src/collection/minByOrNull.ts index 322569d..e78de08 100644 --- a/src/collection/minByOrNull.ts +++ b/src/collection/minByOrNull.ts @@ -2,8 +2,8 @@ export function minByOrNull(value: T[], transform: (it: T) => number): T | nu if (value.length === 0) return null; let minIt = value[0]; let minVal = transform(minIt); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val < minVal) { minIt = it; diff --git a/src/collection/minOf.ts b/src/collection/minOf.ts index 2d14a81..a6f943c 100644 --- a/src/collection/minOf.ts +++ b/src/collection/minOf.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function minOf(value: T[], transform: (it: T) => number): number { if (value.length === 0) error(); let min = transform(value[0]); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val < min) min = val; } diff --git a/src/collection/minOfOrNull.ts b/src/collection/minOfOrNull.ts index ed218d0..42bc37c 100644 --- a/src/collection/minOfOrNull.ts +++ b/src/collection/minOfOrNull.ts @@ -1,8 +1,8 @@ export function minOfOrNull(value: T[], transform: (it: T) => number): number | null { if (value.length === 0) return null; let min = transform(value[0]); - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; const val = transform(it); if (val < min) min = val; } diff --git a/src/collection/minOrNull.ts b/src/collection/minOrNull.ts index 862e233..ff84956 100644 --- a/src/collection/minOrNull.ts +++ b/src/collection/minOrNull.ts @@ -1,8 +1,8 @@ export function minOrNull(value: number[]): number | null { if (value.length === 0) return null; let min = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (it < min) min = it; } return min; diff --git a/src/collection/minWith.ts b/src/collection/minWith.ts index 22a3463..a755102 100644 --- a/src/collection/minWith.ts +++ b/src/collection/minWith.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function minWith(value: T[], compare: (a: T, b: T) => number): T { if (value.length === 0) error(); let min = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (compare(it, min) < 0) min = it; } return min; diff --git a/src/collection/minWithOrNull.ts b/src/collection/minWithOrNull.ts index ebd0b38..956b407 100644 --- a/src/collection/minWithOrNull.ts +++ b/src/collection/minWithOrNull.ts @@ -1,8 +1,8 @@ export function minWithOrNull(value: T[], compare: (a: T, b: T) => number): T | null { if (value.length === 0) return null; let min = value[0]; - for (let index = 1; index < value.length; index++) { - const it = value[index]; + for (let i = 1; i < value.length; i++) { + const it = value[i]; if (compare(it, min) < 0) min = it; } return min; diff --git a/src/collection/reduce.ts b/src/collection/reduce.ts index 2f0c2c7..1b3b768 100644 --- a/src/collection/reduce.ts +++ b/src/collection/reduce.ts @@ -3,8 +3,8 @@ import {error} from "../util/error"; export function reduce(value: T[], accumulate: (acc: T, it: T) => T): T { if (value.length === 0) error(); let acc = value[0]; - for (let index = 1; index < value.length; index++) { - acc = accumulate(acc, value[index]); + for (let i = 1; i < value.length; i++) { + acc = accumulate(acc, value[i]); } return acc; } diff --git a/src/collection/reduceOrNull.ts b/src/collection/reduceOrNull.ts index d4230dc..5a4fdee 100644 --- a/src/collection/reduceOrNull.ts +++ b/src/collection/reduceOrNull.ts @@ -1,8 +1,8 @@ export function reduceOrNull(value: T[], accumulate: (acc: T, it: T) => T): T | null { if (value.length === 0) return null; let acc = value[0]; - for (let index = 1; index < value.length; index++) { - acc = accumulate(acc, value[index]); + for (let i = 1; i < value.length; i++) { + acc = accumulate(acc, value[i]); } return acc; } diff --git a/src/collection/slice.ts b/src/collection/slice.ts index c1cf0a3..0cf0f6f 100644 --- a/src/collection/slice.ts +++ b/src/collection/slice.ts @@ -7,9 +7,8 @@ export function slice(value: T[], start: number, end?: number): T[] { if (start > end) error(); } const result: T[] = []; - const limit = end ?? value.length; - for (let index = start; index < limit; index++) { - result.push(value[index]); + for (let i = start; i < (end ?? value.length); i++) { + result.push(value[i]); } return result; } diff --git a/src/collection/take.ts b/src/collection/take.ts index 08a61ad..07585ff 100644 --- a/src/collection/take.ts +++ b/src/collection/take.ts @@ -3,9 +3,9 @@ import {error} from "../util/error"; export function take(value: T[], count: number): T[] { if (count < 0) error(); const result: T[] = []; - const limit = Math.min(count, value.length); - for (let index = 0; index < limit; index++) { - result.push(value[index]); + const index = Math.min(count, value.length); + for (let i = 0; i < index; i++) { + result.push(value[i]); } return result; } diff --git a/src/collection/takeLast.ts b/src/collection/takeLast.ts new file mode 100644 index 0000000..b0134a4 --- /dev/null +++ b/src/collection/takeLast.ts @@ -0,0 +1,11 @@ +import {error} from "../util/error"; + +export function takeLast(value: T[], count: number): T[] { + if (count < 0) error(); + const result: T[] = []; + const index = Math.max(0, value.length - count); + for (let i = index; i < value.length; i++) { + result.push(value[i]); + } + return result; +} diff --git a/src/collection/takeLastUntil.ts b/src/collection/takeLastUntil.ts new file mode 100644 index 0000000..f64a935 --- /dev/null +++ b/src/collection/takeLastUntil.ts @@ -0,0 +1,11 @@ +export function takeLastUntil(value: T[], predicate: (it: T) => boolean): T[] { + let index = value.length - 1; + while (index >= 0 && !predicate(value[index])) { + index--; + } + const result: T[] = []; + for (let i = index + 1; i < value.length; i++) { + result.push(value[i]); + } + return result; +} diff --git a/src/collection/takeLastWhile.ts b/src/collection/takeLastWhile.ts new file mode 100644 index 0000000..ba9f618 --- /dev/null +++ b/src/collection/takeLastWhile.ts @@ -0,0 +1,11 @@ +export function takeLastWhile(value: T[], predicate: (it: T) => boolean): T[] { + let index = value.length - 1; + while (index >= 0 && predicate(value[index])) { + index--; + } + const result: T[] = []; + for (let i = index + 1; i < value.length; i++) { + result.push(value[i]); + } + return result; +}