Compare commits

...

4 commits

Author SHA1 Message Date
Michaël Lemaire 6d8eef663a Add ienumerate function 2021-09-02 23:13:21 +02:00
Michaël Lemaire 03f050bcfb Update doc 2021-08-30 23:09:42 +02:00
Michaël Lemaire 089920e4d3 Add iminBy and imaxBy 2021-08-30 23:07:44 +02:00
Michaël Lemaire 8fbb5c4ad1 Fix imapfilter typing 2021-08-26 23:50:26 +02:00
4 changed files with 71 additions and 6 deletions

View file

@ -58,6 +58,8 @@ isum(i1); // 6
icat(iarray(["a", "b", "c"])); // abc icat(iarray(["a", "b", "c"])); // abc
imin(i1); // 1 imin(i1); // 1
imax(i1); // 3 imax(i1); // 3
iminBy(i1, (x) => -x); // 3
imaxBy(i1, (x) => -x); // 1
// Transform iterables // Transform iterables
iloop(i1); // 1 2 3 1 2 3 ... iloop(i1); // 1 2 3 1 2 3 ...
@ -67,6 +69,7 @@ ifilter(i3, (x) => x % 4 == 0); // 0 -4 -8 -12 ...
imapfilter(i1, (x) => x != 4 ? x * 2 : null); // 2 6 imapfilter(i1, (x) => x != 4 ? x * 2 : null); // 2 6
ipartition(i3, (x) => x % 4 == 0); // [0 -4 -8 ..., -1 -2 -3 -5 ...] ipartition(i3, (x) => x % 4 == 0); // [0 -4 -8 ..., -1 -2 -3 -5 ...]
iunique(iarray([1, 4, 2, 4, 3, 1, 5])); // 1 4 2 3 5 iunique(iarray([1, 4, 2, 4, 3, 1, 5])); // 1 4 2 3 5
ienumerate(iarray(["a", "b", "c"])); // [0, "a"] [1, "b"] [2, "c"]
// Combine iterables // Combine iterables
ichain(i1, i2); // 1 2 3 4 ichain(i1, i2); // 1 2 3 4

View file

@ -24,6 +24,8 @@ isum(i1); // 6
icat(iarray(["a", "b", "c"])); // abc icat(iarray(["a", "b", "c"])); // abc
imin(i1); // 1 imin(i1); // 1
imax(i1); // 3 imax(i1); // 3
iminBy(i1, (x) => -x); // 3
imaxBy(i1, (x) => -x); // 1
// Transform iterables // Transform iterables
iloop(i1); // 1 2 3 1 2 3 ... iloop(i1); // 1 2 3 1 2 3 ...
@ -33,6 +35,7 @@ ifilter(i3, (x) => x % 4 == 0); // 0 -4 -8 -12 ...
imapfilter(i1, (x) => x != 4 ? x * 2 : null); // 2 6 imapfilter(i1, (x) => x != 4 ? x * 2 : null); // 2 6
ipartition(i3, (x) => x % 4 == 0); // [0 -4 -8 ..., -1 -2 -3 -5 ...] ipartition(i3, (x) => x % 4 == 0); // [0 -4 -8 ..., -1 -2 -3 -5 ...]
iunique(iarray([1, 4, 2, 4, 3, 1, 5])); // 1 4 2 3 5 iunique(iarray([1, 4, 2, 4, 3, 1, 5])); // 1 4 2 3 5
ienumerate(iarray(["a", "b", "c"])); // [0, "a"] [1, "b"] [2, "c"]
// Combine iterables // Combine iterables
ichain(i1, i2); // 1 2 3 4 ichain(i1, i2); // 1 2 3 4

View file

@ -8,6 +8,7 @@ import {
ichainit, ichainit,
icombine, icombine,
IEMPTY, IEMPTY,
ienumerate,
ifilter, ifilter,
ifilterclass, ifilterclass,
ifiltertype, ifiltertype,
@ -20,7 +21,9 @@ import {
imapfilter, imapfilter,
imaterialize, imaterialize,
imax, imax,
imaxBy,
imin, imin,
iminBy,
ipartition, ipartition,
irange, irange,
irecur, irecur,
@ -284,6 +287,15 @@ describe("Iterators", () => {
]); ]);
}); });
it("enumerate iterators", () => {
let iterator = ienumerate(iarray(["a", "b", "c"]));
checkit(iterator, [
[0, "a"],
[1, "b"],
[2, "c"],
]);
});
it("zips iterators", () => { it("zips iterators", () => {
checkit(izip(IEMPTY, IEMPTY), []); checkit(izip(IEMPTY, IEMPTY), []);
checkit(izip(iarray([1, 2, 3]), iarray(["a", "b"])), [[1, "a"], [ checkit(izip(iarray([1, 2, 3]), iarray(["a", "b"])), [[1, "a"], [
@ -340,5 +352,11 @@ describe("Iterators", () => {
expect(imax(IEMPTY)).toEqual(-Infinity); expect(imax(IEMPTY)).toEqual(-Infinity);
expect(imax(iarray([3, 8, 2, 4]))).toEqual(8); expect(imax(iarray([3, 8, 2, 4]))).toEqual(8);
expect(iminBy(IEMPTY, (x) => x)).toBeUndefined();
expect(iminBy(["aaa", "b", "cc"], (x) => x.length)).toEqual("b");
expect(imaxBy(IEMPTY, (x) => x)).toBeUndefined();
expect(imaxBy(["aaa", "b", "cc"], (x) => x.length)).toEqual("aaa");
}); });
}); });

53
mod.ts
View file

@ -341,17 +341,16 @@ export function ifilter<T>(
/** /**
* Apply map, and filter invalid results in the same pass. * Apply map, and filter invalid results in the same pass.
*/ */
export function imapfilter<T1, T2, E>( export function imapfilter<T1, T2>(
iterable: Iterable<T1>, iterable: Iterable<T1>,
mapfunc: (_: T1) => Exclude<T2, E> | typeof exclusion, mapfunc: (_: T1) => T2 | null,
exclusion: E = null as unknown as E, ): Iterable<Exclude<T2, null>> {
): Iterable<T2> {
return { return {
[Symbol.iterator]: function* () { [Symbol.iterator]: function* () {
for (let value of iterable) { for (let value of iterable) {
const mapped = mapfunc(value); const mapped = mapfunc(value);
if (mapped !== exclusion) { if (mapped !== null) {
yield mapped as T2; yield mapped as Exclude<T2, null>;
} }
} }
}, },
@ -391,6 +390,24 @@ export function icombine<T1, T2>(
return ichainit(imap(it1, (v1) => imap(it2, (v2): [T1, T2] => [v1, v2]))); return ichainit(imap(it1, (v1) => imap(it2, (v2): [T1, T2] => [v1, v2])));
} }
/**
* Enumerate another iterable, adding the index before the value.
*/
export function ienumerate<T>(it: Iterable<T>): Iterable<[number, T]> {
return {
[Symbol.iterator]: function* () {
const iterator = it[Symbol.iterator]();
let state = iterator.next();
let idx = 0;
while (!state.done) {
yield [idx, state.value];
state = iterator.next();
idx += 1;
}
},
};
}
/** /**
* Advance through two iterables at the same time, yielding item pairs * Advance through two iterables at the same time, yielding item pairs
* *
@ -517,3 +534,27 @@ export const imin = (iterable: Iterable<number>) =>
ireduce(iterable, Math.min, Infinity); ireduce(iterable, Math.min, Infinity);
export const imax = (iterable: Iterable<number>) => export const imax = (iterable: Iterable<number>) =>
ireduce(iterable, Math.max, -Infinity); ireduce(iterable, Math.max, -Infinity);
/**
* Min/max by key function
*/
export function iminBy<T>(
iterable: Iterable<T>,
key: (value: T) => number,
): T | undefined {
return ireduce(
iterable,
(item1, item2) =>
(typeof item1 == "undefined" || typeof item2 == "undefined") ||
(key(item1) > key(item2))
? item2
: item1,
undefined,
);
}
export function imaxBy<T>(
iterable: Iterable<T>,
key: (value: T) => number,
): T | undefined {
return iminBy(iterable, (value) => -key(value));
}