Compare commits

..

6 Commits

Author SHA1 Message Date
babb1e0247 Merge pull request 'develop' (#2) from develop into main
All checks were successful
/ publish (push) Successful in 9s
Reviewed-on: #2
2026-05-08 20:06:14 +00:00
98bd6b573e Implement dropLast/takeLast 2026-05-08 22:04:57 +02:00
78ae570bcb Refactor 2026-05-08 22:04:56 +02:00
f933ce28b9 Merge pull request 'Implement toObject' (#1) from develop into main
All checks were successful
/ publish (push) Successful in 10s
Reviewed-on: #1
2026-05-07 19:35:52 +00:00
d4875a8ff0 Implement toObject 2026-05-07 21:33:30 +02:00
a1bbf7cd1a Small Refactor 2026-04-29 18:24:32 +02:00
33 changed files with 168 additions and 63 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@infendro/collection",
"version": "0.0.1",
"version": "0.0.3",
"scripts": {
"build": "tsc"
},

View File

@@ -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,10 +72,14 @@ 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";
@@ -85,6 +92,7 @@ export type Collection<T> = {
toArray(): T[]
toSet(): Set<T>
toMap<K, V>(this: Collection<[K, V]>): Map<K, V>
toObject<K extends Key, V>(this: Collection<[K, V]>): Object<K, V>
onEach(action: (it: T) => void): Collection<T>
forEach(action: (it: T) => void): void
@@ -155,9 +163,15 @@ export type Collection<T> = {
drop(count: number): Collection<T>
dropWhile(predicate: (it: T) => boolean): Collection<T>
dropUntil(predicate: (it: T) => boolean): Collection<T>
dropLast(count: number): Collection<T>
dropLastWhile(predicate: (it: T) => boolean): Collection<T>
dropLastUntil(predicate: (it: T) => boolean): Collection<T>
take(count: number): Collection<T>
takeWhile(predicate: (it: T) => boolean): Collection<T>
takeUntil(predicate: (it: T) => boolean): Collection<T>
takeLast(count: number): Collection<T>
takeLastWhile(predicate: (it: T) => boolean): Collection<T>
takeLastUntil(predicate: (it: T) => boolean): Collection<T>
slice(start: number, end?: number): Collection<T>
map<R>(transform: (it: T) => R): Collection<R>
@@ -199,6 +213,9 @@ function wrap<T>(value: T[]): Collection<T> {
toMap<K, V>() {
return toMap(value as [K, V][]);
},
toObject<K extends Key, V>() {
return toObject(value as [K, V][]);
},
onEach(action) {
return wrap(onEach(value, action));
},
@@ -370,6 +387,15 @@ function wrap<T>(value: T[]): Collection<T> {
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));
},
@@ -379,6 +405,15 @@ function wrap<T>(value: T[]): Collection<T> {
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));
},

View File

@@ -0,0 +1,10 @@
import {error} from "../util/error";
export function dropLast<T>(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;
}

View File

@@ -0,0 +1,11 @@
export function dropLastUntil<T>(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;
}

View File

@@ -0,0 +1,11 @@
export function dropLastWhile<T>(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;
}

View File

@@ -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;

View File

@@ -2,15 +2,15 @@ import {error} from "../util/error";
export function maxBy<T>(value: T[], transform: (it: T) => number): T {
if (value.length === 0) error();
let max = value[0];
let maxVal = transform(max);
for (let index = 1; index < value.length; index++) {
const it = value[index];
let maxIt = value[0];
let maxVal = transform(maxIt);
for (let i = 1; i < value.length; i++) {
const it = value[i];
const val = transform(it);
if (val > maxVal) {
max = it;
maxIt = it;
maxVal = val;
}
}
return max;
return maxIt;
}

View File

@@ -1,14 +1,14 @@
export function maxByOrNull<T>(value: T[], transform: (it: T) => number): T | null {
if (value.length === 0) return null;
let max = value[0];
let maxVal = transform(max);
for (let index = 1; index < value.length; index++) {
const it = value[index];
let maxIt = value[0];
let maxVal = transform(maxIt);
for (let i = 1; i < value.length; i++) {
const it = value[i];
const val = transform(it);
if (val > maxVal) {
max = it;
maxIt = it;
maxVal = val;
}
}
return max;
return maxIt;
}

View File

@@ -3,8 +3,8 @@ import {error} from "../util/error";
export function maxOf<T>(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;
}

View File

@@ -1,8 +1,8 @@
export function maxOfOrNull<T>(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;
}

View File

@@ -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;

View File

@@ -3,8 +3,8 @@ import {error} from "../util/error";
export function maxWith<T>(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;

View File

@@ -1,8 +1,8 @@
export function maxWithOrNull<T>(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;

View File

@@ -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;

View File

@@ -2,15 +2,15 @@ import {error} from "../util/error";
export function minBy<T>(value: T[], transform: (it: T) => number): T {
if (value.length === 0) error();
let min = value[0];
let minVal = transform(min);
for (let index = 1; index < value.length; index++) {
const it = value[index];
let minIt = value[0];
let minVal = transform(minIt);
for (let i = 1; i < value.length; i++) {
const it = value[i];
const val = transform(it);
if (val < minVal) {
min = it;
minIt = it;
minVal = val;
}
}
return min;
return minIt;
}

View File

@@ -1,14 +1,14 @@
export function minByOrNull<T>(value: T[], transform: (it: T) => number): T | null {
if (value.length === 0) return null;
let min = value[0];
let minVal = transform(min);
for (let index = 1; index < value.length; index++) {
const it = value[index];
let minIt = value[0];
let minVal = transform(minIt);
for (let i = 1; i < value.length; i++) {
const it = value[i];
const val = transform(it);
if (val < minVal) {
min = it;
minIt = it;
minVal = val;
}
}
return min;
return minIt;
}

View File

@@ -3,8 +3,8 @@ import {error} from "../util/error";
export function minOf<T>(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;
}

View File

@@ -1,8 +1,8 @@
export function minOfOrNull<T>(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;
}

View File

@@ -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;

View File

@@ -3,8 +3,8 @@ import {error} from "../util/error";
export function minWith<T>(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;

View File

@@ -1,8 +1,8 @@
export function minWithOrNull<T>(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;

View File

@@ -3,8 +3,8 @@ import {error} from "../util/error";
export function reduce<T>(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;
}

View File

@@ -1,8 +1,8 @@
export function reduceOrNull<T>(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;
}

View File

@@ -1,3 +1,3 @@
export function reversed<T>(value: T[]): T[] {
return [...value].reverse();
return value.toReversed();
}

View File

@@ -7,9 +7,8 @@ export function slice<T>(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;
}

View File

@@ -1,3 +1,3 @@
export function sorted(value: number[]): number[] {
return [...value].sort((a, b) => a - b);
return value.toSorted((a, b) => a - b);
}

View File

@@ -1,3 +1,3 @@
export function sortedBy<T>(value: T[], transform: (it: T) => number): T[] {
return [...value].sort((a, b) => transform(a) - transform(b));
return value.toSorted((a, b) => transform(a) - transform(b));
}

View File

@@ -1,3 +1,3 @@
export function sortedWith<T>(value: T[], compare: (a: T, b: T) => number): T[] {
return [...value].sort(compare);
return value.toSorted(compare);
}

View File

@@ -3,9 +3,9 @@ import {error} from "../util/error";
export function take<T>(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;
}

View File

@@ -0,0 +1,11 @@
import {error} from "../util/error";
export function takeLast<T>(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;
}

View File

@@ -0,0 +1,11 @@
export function takeLastUntil<T>(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;
}

View File

@@ -0,0 +1,11 @@
export function takeLastWhile<T>(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;
}

View File

@@ -0,0 +1,6 @@
export type Key = keyof any
export type Object<K extends Key, V> = { [key in K]?: V }
export function toObject<K extends Key, V>(value: [K, V][]): Object<K, V> {
return Object.fromEntries(value) as Object<K, V>;
}