Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
Michaël Lemaire | 6d8eef663a | ||
Michaël Lemaire | 03f050bcfb | ||
Michaël Lemaire | 089920e4d3 | ||
Michaël Lemaire | 8fbb5c4ad1 | ||
Michaël Lemaire | 43d5678697 |
|
@ -58,14 +58,18 @@ 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 ...
|
||||||
iskip(i3, 2); // -2 -3 -4 -5 -6 ...
|
iskip(i3, 2); // -2 -3 -4 -5 -6 ...
|
||||||
imap(i1, (x) => x * 2); // 2 4 6
|
imap(i1, (x) => x * 2); // 2 4 6
|
||||||
ifilter(i3, (x) => x % 4 == 0); // 0 -4 -8 -12 ...
|
ifilter(i3, (x) => x % 4 == 0); // 0 -4 -8 -12 ...
|
||||||
|
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
|
||||||
|
|
|
@ -24,14 +24,18 @@ 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 ...
|
||||||
iskip(i3, 2); // -2 -3 -4 -5 -6 ...
|
iskip(i3, 2); // -2 -3 -4 -5 -6 ...
|
||||||
imap(i1, (x) => x * 2); // 2 4 6
|
imap(i1, (x) => x * 2); // 2 4 6
|
||||||
ifilter(i3, (x) => x % 4 == 0); // 0 -4 -8 -12 ...
|
ifilter(i3, (x) => x % 4 == 0); // 0 -4 -8 -12 ...
|
||||||
|
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
|
||||||
|
|
31
mod.test.ts
31
mod.test.ts
|
@ -8,6 +8,7 @@ import {
|
||||||
ichainit,
|
ichainit,
|
||||||
icombine,
|
icombine,
|
||||||
IEMPTY,
|
IEMPTY,
|
||||||
|
ienumerate,
|
||||||
ifilter,
|
ifilter,
|
||||||
ifilterclass,
|
ifilterclass,
|
||||||
ifiltertype,
|
ifiltertype,
|
||||||
|
@ -17,9 +18,12 @@ import {
|
||||||
ilength,
|
ilength,
|
||||||
iloop,
|
iloop,
|
||||||
imap,
|
imap,
|
||||||
|
imapfilter,
|
||||||
imaterialize,
|
imaterialize,
|
||||||
imax,
|
imax,
|
||||||
|
imaxBy,
|
||||||
imin,
|
imin,
|
||||||
|
iminBy,
|
||||||
ipartition,
|
ipartition,
|
||||||
irange,
|
irange,
|
||||||
irecur,
|
irecur,
|
||||||
|
@ -241,10 +245,20 @@ describe("Iterators", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("filters an iterator with a predicate", () => {
|
it("filters an iterator with a predicate", () => {
|
||||||
checkit(imap(IEMPTY, (i) => i % 3 == 0), []);
|
checkit(ifilter(IEMPTY, (i) => i % 3 == 0), []);
|
||||||
checkit(ifilter(irange(12), (i) => i % 3 == 0), [0, 3, 6, 9]);
|
checkit(ifilter(irange(12), (i) => i % 3 == 0), [0, 3, 6, 9]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("maps and filters in a single pass", () => {
|
||||||
|
checkit(imapfilter(IEMPTY, (i) => i % 2 == 0 ? -i : null), []);
|
||||||
|
checkit(imapfilter(irange(8), (i) => i % 2 == 0 ? -i : null), [
|
||||||
|
-0,
|
||||||
|
-2,
|
||||||
|
-4,
|
||||||
|
-6,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("filters an iterator with a type guard", () => {
|
it("filters an iterator with a type guard", () => {
|
||||||
let result: Iterable<number> = ifiltertype(
|
let result: Iterable<number> = ifiltertype(
|
||||||
<(number | string)[]> [1, "a", 2, "b"],
|
<(number | string)[]> [1, "a", 2, "b"],
|
||||||
|
@ -273,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"], [
|
||||||
|
@ -329,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");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
61
mod.ts
61
mod.ts
|
@ -338,6 +338,25 @@ export function ifilter<T>(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply map, and filter invalid results in the same pass.
|
||||||
|
*/
|
||||||
|
export function imapfilter<T1, T2>(
|
||||||
|
iterable: Iterable<T1>,
|
||||||
|
mapfunc: (_: T1) => T2 | null,
|
||||||
|
): Iterable<Exclude<T2, null>> {
|
||||||
|
return {
|
||||||
|
[Symbol.iterator]: function* () {
|
||||||
|
for (let value of iterable) {
|
||||||
|
const mapped = mapfunc(value);
|
||||||
|
if (mapped !== null) {
|
||||||
|
yield mapped as Exclude<T2, null>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type filter, to return a list of instances of a given type
|
* Type filter, to return a list of instances of a given type
|
||||||
*/
|
*/
|
||||||
|
@ -371,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
|
||||||
*
|
*
|
||||||
|
@ -497,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));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue