Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/common/iterator.ts
3291 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { isIterable } from './types.js';
7
8
export namespace Iterable {
9
10
export function is<T = any>(thing: unknown): thing is Iterable<T> {
11
return !!thing && typeof thing === 'object' && typeof (thing as Iterable<T>)[Symbol.iterator] === 'function';
12
}
13
14
const _empty: Iterable<any> = Object.freeze([]);
15
export function empty<T = any>(): Iterable<T> {
16
return _empty;
17
}
18
19
export function* single<T>(element: T): Iterable<T> {
20
yield element;
21
}
22
23
export function wrap<T>(iterableOrElement: Iterable<T> | T): Iterable<T> {
24
if (is(iterableOrElement)) {
25
return iterableOrElement;
26
} else {
27
return single(iterableOrElement);
28
}
29
}
30
31
export function from<T>(iterable: Iterable<T> | undefined | null): Iterable<T> {
32
return iterable || _empty;
33
}
34
35
export function* reverse<T>(array: ReadonlyArray<T>): Iterable<T> {
36
for (let i = array.length - 1; i >= 0; i--) {
37
yield array[i];
38
}
39
}
40
41
export function isEmpty<T>(iterable: Iterable<T> | undefined | null): boolean {
42
return !iterable || iterable[Symbol.iterator]().next().done === true;
43
}
44
45
export function first<T>(iterable: Iterable<T>): T | undefined {
46
return iterable[Symbol.iterator]().next().value;
47
}
48
49
export function some<T>(iterable: Iterable<T>, predicate: (t: T, i: number) => unknown): boolean {
50
let i = 0;
51
for (const element of iterable) {
52
if (predicate(element, i++)) {
53
return true;
54
}
55
}
56
return false;
57
}
58
59
export function every<T>(iterable: Iterable<T>, predicate: (t: T, i: number) => unknown): boolean {
60
let i = 0;
61
for (const element of iterable) {
62
if (!predicate(element, i++)) {
63
return false;
64
}
65
}
66
return true;
67
}
68
69
export function find<T, R extends T>(iterable: Iterable<T>, predicate: (t: T) => t is R): R | undefined;
70
export function find<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): T | undefined;
71
export function find<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): T | undefined {
72
for (const element of iterable) {
73
if (predicate(element)) {
74
return element;
75
}
76
}
77
78
return undefined;
79
}
80
81
export function filter<T, R extends T>(iterable: Iterable<T>, predicate: (t: T) => t is R): Iterable<R>;
82
export function filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T>;
83
export function* filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T> {
84
for (const element of iterable) {
85
if (predicate(element)) {
86
yield element;
87
}
88
}
89
}
90
91
export function* map<T, R>(iterable: Iterable<T>, fn: (t: T, index: number) => R): Iterable<R> {
92
let index = 0;
93
for (const element of iterable) {
94
yield fn(element, index++);
95
}
96
}
97
98
export function* flatMap<T, R>(iterable: Iterable<T>, fn: (t: T, index: number) => Iterable<R>): Iterable<R> {
99
let index = 0;
100
for (const element of iterable) {
101
yield* fn(element, index++);
102
}
103
}
104
105
export function* concat<T>(...iterables: (Iterable<T> | T)[]): Iterable<T> {
106
for (const item of iterables) {
107
if (isIterable(item)) {
108
yield* item;
109
} else {
110
yield item;
111
}
112
}
113
}
114
115
export function reduce<T, R>(iterable: Iterable<T>, reducer: (previousValue: R, currentValue: T) => R, initialValue: R): R {
116
let value = initialValue;
117
for (const element of iterable) {
118
value = reducer(value, element);
119
}
120
return value;
121
}
122
123
export function length<T>(iterable: Iterable<T>): number {
124
let count = 0;
125
for (const _ of iterable) {
126
count++;
127
}
128
return count;
129
}
130
131
/**
132
* Returns an iterable slice of the array, with the same semantics as `array.slice()`.
133
*/
134
export function* slice<T>(arr: ReadonlyArray<T>, from: number, to = arr.length): Iterable<T> {
135
if (from < -arr.length) {
136
from = 0;
137
}
138
if (from < 0) {
139
from += arr.length;
140
}
141
142
if (to < 0) {
143
to += arr.length;
144
} else if (to > arr.length) {
145
to = arr.length;
146
}
147
148
for (; from < to; from++) {
149
yield arr[from];
150
}
151
}
152
153
/**
154
* Consumes `atMost` elements from iterable and returns the consumed elements,
155
* and an iterable for the rest of the elements.
156
*/
157
export function consume<T>(iterable: Iterable<T>, atMost: number = Number.POSITIVE_INFINITY): [T[], Iterable<T>] {
158
const consumed: T[] = [];
159
160
if (atMost === 0) {
161
return [consumed, iterable];
162
}
163
164
const iterator = iterable[Symbol.iterator]();
165
166
for (let i = 0; i < atMost; i++) {
167
const next = iterator.next();
168
169
if (next.done) {
170
return [consumed, Iterable.empty()];
171
}
172
173
consumed.push(next.value);
174
}
175
176
return [consumed, { [Symbol.iterator]() { return iterator; } }];
177
}
178
179
export async function asyncToArray<T>(iterable: AsyncIterable<T>): Promise<T[]> {
180
const result: T[] = [];
181
for await (const item of iterable) {
182
result.push(item);
183
}
184
return result;
185
}
186
187
export async function asyncToArrayFlat<T>(iterable: AsyncIterable<T[]>): Promise<T[]> {
188
let result: T[] = [];
189
for await (const item of iterable) {
190
result = result.concat(item);
191
}
192
return result;
193
}
194
}
195
196