Skip to content

Commit fc85b33

Browse files
committed
Add first and firstAsync
1 parent 6b18781 commit fc85b33

2 files changed

Lines changed: 53 additions & 3 deletions

File tree

generator.test.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import {
2222
takeAsync,
2323
takeWhile,
2424
takeWhileAsync,
25+
first,
26+
firstAsync,
2527
toAsync,
2628
} from "./generator.ts";
2729

@@ -107,16 +109,17 @@ Deno.test("dedupe removes duplicate values based on key", async () => {
107109
]);
108110
});
109111

110-
const sleep = <T>(value: T, ms: number): Promise<T> =>
112+
const sleep = (ms: number): Promise<void> =>
111113
new Promise((resolve) => {
112114
setTimeout(() => {
113-
resolve(value);
115+
resolve();
114116
}, ms);
115117
});
116118

117119
async function* sleepyIter<T>(values: Iterable<T>): AsyncGenerator<T> {
120+
await sleep(1);
118121
for (const n of values) {
119-
yield await sleep(n, 1);
122+
yield await n;
120123
}
121124
}
122125

@@ -197,6 +200,33 @@ Deno.test(
197200
},
198201
);
199202

203+
Deno.test("first returns the first item from an iterable", () => {
204+
const numbers = [1, 2, 3, 4, 5];
205+
const firstItem = first(numbers);
206+
assertEquals(firstItem, 1);
207+
});
208+
209+
Deno.test("first returns undefined for empty iterable", () => {
210+
const empty: number[] = [];
211+
const firstItem = first(empty);
212+
assertEquals(firstItem, undefined);
213+
});
214+
215+
Deno.test(
216+
"firstAsync returns the first item from an async iterable",
217+
async () => {
218+
const numbers = [1, 2, 3, 4, 5];
219+
const firstItem = await firstAsync(sleepyIter(numbers));
220+
assertEquals(firstItem, 1);
221+
},
222+
);
223+
224+
Deno.test("firstAsync returns undefined for empty async iterable", async () => {
225+
const empty: number[] = [];
226+
const firstItem = await firstAsync(sleepyIter(empty));
227+
assertEquals(firstItem, undefined);
228+
});
229+
200230
Deno.test(
201231
"dedupeAsync removes duplicate values based on key asynchronously",
202232
async () => {

generator.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ export function* takeWhile<T>(
133133
}
134134
}
135135

136+
/** Takes the first item from the iterator */
137+
export function first<T>(iter: Iterable<T>): T | undefined {
138+
for (const value of iter) {
139+
return value;
140+
}
141+
}
142+
143+
/**
144+
* Deduplicates values using `getKey` to derive a string key representing the value
145+
* @param iter - an iterable of values to deduplicate
146+
* @param getKey - a function that returns a string key representing the value
147+
*/
136148
export function* dedupe<T>(
137149
iter: Iterable<T>,
138150
getKey: (value: T) => string,
@@ -293,6 +305,14 @@ export async function* takeWhileAsync<T>(
293305
}
294306
}
295307

308+
export async function firstAsync<T>(
309+
iter: AwaitableIterable<T>,
310+
): Promise<T | undefined> {
311+
for await (const value of iter) {
312+
return value;
313+
}
314+
}
315+
296316
export async function* dedupeAsync<T>(
297317
iter: AwaitableIterable<T>,
298318
getKey: (value: T) => string,

0 commit comments

Comments
 (0)