Skip to content

Commit 145758a

Browse files
committed
feat: Add find utility function for Iterables
1 parent 286f815 commit 145758a

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

src/util/IterableUtil.ts

+21
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,27 @@ export function* concat<T>(iterables: Iterable<Iterable<T>>): Iterable<T> {
5050
}
5151
}
5252

53+
/**
54+
* Returns the first element in the provided iterable that satisfies the provided testing function.
55+
* If no values satisfy the testing function, `undefined` is returned.
56+
* Similar to the {@link Array.prototype.find} function.
57+
* See the documentation of the above function for more details.
58+
*
59+
* @param iterable - Iterable on which to call the map function.
60+
* @param callbackFn - Function that is called to test every element.
61+
* @param thisArg - Value to use as `this` when executing `callbackFn`.
62+
*/
63+
export function find<T>(iterable: Iterable<T>, callbackFn: (element: T, index: number) => boolean, thisArg?: any):
64+
T | undefined {
65+
const boundMapFn = callbackFn.bind(thisArg);
66+
const count = 0;
67+
for (const value of iterable) {
68+
if (boundMapFn(value, count)) {
69+
return value;
70+
}
71+
}
72+
}
73+
5374
/**
5475
* Similar to the {@link Array.prototype.reduce} function, but for an iterable.
5576
* See the documentation of the above function for more details.

test/unit/util/IterableUtil.test.ts

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
1-
import { concat, filter, map, reduce } from '../../../src/util/IterableUtil';
1+
import { concat, filter, find, map, reduce } from '../../../src/util/IterableUtil';
22

33
describe('IterableUtil', (): void => {
4-
describe('#mapIterable', (): void => {
4+
describe('#map', (): void => {
55
it('maps the values to a new iterable.', async(): Promise<void> => {
66
const input = [ 1, 2, 3 ];
77
expect([ ...map(input, (val): number => val + 3) ]).toEqual([ 4, 5, 6 ]);
88
});
99
});
1010

11-
describe('#filterIterable', (): void => {
11+
describe('#filter', (): void => {
1212
it('filters the values of the iterable.', async(): Promise<void> => {
1313
const input = [ 1, 2, 3 ];
1414
expect([ ...filter(input, (val): boolean => val % 2 === 1) ]).toEqual([ 1, 3 ]);
1515
});
1616
});
1717

18-
describe('#concatIterables', (): void => {
18+
describe('#concat', (): void => {
1919
it('concatenates all the iterables.', async(): Promise<void> => {
2020
const input = [[ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]];
2121
expect([ ...concat(input) ]).toEqual([ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]);
2222
});
2323
});
2424

25-
describe('#reduceIterable', (): void => {
25+
describe('#find', (): void => {
26+
it('finds the matching value.', async(): Promise<void> => {
27+
const input = [[ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]];
28+
expect(find(input, (entry): boolean => entry.includes(5))).toEqual([ 4, 5, 6 ]);
29+
});
30+
31+
it('returns undefined if there is no match.', async(): Promise<void> => {
32+
const input = [[ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]];
33+
expect(find(input, (entry): boolean => entry.includes(0))).toBeUndefined();
34+
});
35+
});
36+
37+
describe('#reduce', (): void => {
2638
it('reduces the values in an iterable.', async(): Promise<void> => {
2739
const input = [ 1, 2, 3 ];
2840
expect(reduce(input, (acc, cur): number => acc + cur)).toBe(6);

0 commit comments

Comments
 (0)