Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/test/common/arrays.test.ts
3296 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
import assert from 'assert';
6
import * as arrays from '../../common/arrays.js';
7
import * as arraysFind from '../../common/arraysFind.js';
8
import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js';
9
10
suite('Arrays', () => {
11
12
ensureNoDisposablesAreLeakedInTestSuite();
13
14
test('removeFastWithoutKeepingOrder', () => {
15
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
16
arrays.removeFastWithoutKeepingOrder(array, 1);
17
assert.deepStrictEqual(array, [1, 69, 5, 7, 55, 59, 60, 61, 64]);
18
19
arrays.removeFastWithoutKeepingOrder(array, 0);
20
assert.deepStrictEqual(array, [64, 69, 5, 7, 55, 59, 60, 61]);
21
22
arrays.removeFastWithoutKeepingOrder(array, 7);
23
assert.deepStrictEqual(array, [64, 69, 5, 7, 55, 59, 60]);
24
});
25
26
test('findFirst', () => {
27
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
28
29
let idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 0);
30
assert.strictEqual(array[idx], 1);
31
32
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e > 1);
33
assert.strictEqual(array[idx], 4);
34
35
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 8);
36
assert.strictEqual(array[idx], 55);
37
38
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 61);
39
assert.strictEqual(array[idx], 61);
40
41
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 69);
42
assert.strictEqual(array[idx], 69);
43
44
idx = arraysFind.findFirstIdxMonotonousOrArrLen(array, e => e >= 70);
45
assert.strictEqual(idx, array.length);
46
47
idx = arraysFind.findFirstIdxMonotonousOrArrLen([], e => e >= 0);
48
assert.strictEqual(array[idx], 1);
49
});
50
51
test('quickSelect', () => {
52
53
function assertMedian(expexted: number, data: number[], nth: number = Math.floor(data.length / 2)) {
54
const compare = (a: number, b: number) => a - b;
55
const actual1 = arrays.quickSelect(nth, data, compare);
56
assert.strictEqual(actual1, expexted);
57
58
const actual2 = data.slice().sort(compare)[nth];
59
assert.strictEqual(actual2, expexted);
60
}
61
62
assertMedian(5, [9, 1, 0, 2, 3, 4, 6, 8, 7, 10, 5]);
63
assertMedian(8, [9, 1, 0, 2, 3, 4, 6, 8, 7, 10, 5], 8);
64
assertMedian(8, [13, 4, 8]);
65
assertMedian(4, [13, 4, 8, 4, 4]);
66
assertMedian(13, [13, 4, 8], 2);
67
});
68
69
test('sortedDiff', () => {
70
function compare(a: number, b: number): number {
71
return a - b;
72
}
73
74
let d = arrays.sortedDiff([1, 2, 4], [], compare);
75
assert.deepStrictEqual(d, [
76
{ start: 0, deleteCount: 3, toInsert: [] }
77
]);
78
79
d = arrays.sortedDiff([], [1, 2, 4], compare);
80
assert.deepStrictEqual(d, [
81
{ start: 0, deleteCount: 0, toInsert: [1, 2, 4] }
82
]);
83
84
d = arrays.sortedDiff([1, 2, 4], [1, 2, 4], compare);
85
assert.deepStrictEqual(d, []);
86
87
d = arrays.sortedDiff([1, 2, 4], [2, 3, 4, 5], compare);
88
assert.deepStrictEqual(d, [
89
{ start: 0, deleteCount: 1, toInsert: [] },
90
{ start: 2, deleteCount: 0, toInsert: [3] },
91
{ start: 3, deleteCount: 0, toInsert: [5] },
92
]);
93
94
d = arrays.sortedDiff([2, 3, 4, 5], [1, 2, 4], compare);
95
assert.deepStrictEqual(d, [
96
{ start: 0, deleteCount: 0, toInsert: [1] },
97
{ start: 1, deleteCount: 1, toInsert: [] },
98
{ start: 3, deleteCount: 1, toInsert: [] },
99
]);
100
101
d = arrays.sortedDiff([1, 3, 5, 7], [5, 9, 11], compare);
102
assert.deepStrictEqual(d, [
103
{ start: 0, deleteCount: 2, toInsert: [] },
104
{ start: 3, deleteCount: 1, toInsert: [9, 11] }
105
]);
106
107
d = arrays.sortedDiff([1, 3, 7], [5, 9, 11], compare);
108
assert.deepStrictEqual(d, [
109
{ start: 0, deleteCount: 3, toInsert: [5, 9, 11] }
110
]);
111
});
112
113
test('delta sorted arrays', function () {
114
function compare(a: number, b: number): number {
115
return a - b;
116
}
117
118
let d = arrays.delta([1, 2, 4], [], compare);
119
assert.deepStrictEqual(d.removed, [1, 2, 4]);
120
assert.deepStrictEqual(d.added, []);
121
122
d = arrays.delta([], [1, 2, 4], compare);
123
assert.deepStrictEqual(d.removed, []);
124
assert.deepStrictEqual(d.added, [1, 2, 4]);
125
126
d = arrays.delta([1, 2, 4], [1, 2, 4], compare);
127
assert.deepStrictEqual(d.removed, []);
128
assert.deepStrictEqual(d.added, []);
129
130
d = arrays.delta([1, 2, 4], [2, 3, 4, 5], compare);
131
assert.deepStrictEqual(d.removed, [1]);
132
assert.deepStrictEqual(d.added, [3, 5]);
133
134
d = arrays.delta([2, 3, 4, 5], [1, 2, 4], compare);
135
assert.deepStrictEqual(d.removed, [3, 5]);
136
assert.deepStrictEqual(d.added, [1]);
137
138
d = arrays.delta([1, 3, 5, 7], [5, 9, 11], compare);
139
assert.deepStrictEqual(d.removed, [1, 3, 7]);
140
assert.deepStrictEqual(d.added, [9, 11]);
141
142
d = arrays.delta([1, 3, 7], [5, 9, 11], compare);
143
assert.deepStrictEqual(d.removed, [1, 3, 7]);
144
assert.deepStrictEqual(d.added, [5, 9, 11]);
145
});
146
147
test('binarySearch', () => {
148
function compare(a: number, b: number): number {
149
return a - b;
150
}
151
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
152
153
assert.strictEqual(arrays.binarySearch(array, 1, compare), 0);
154
assert.strictEqual(arrays.binarySearch(array, 5, compare), 2);
155
156
// insertion point
157
assert.strictEqual(arrays.binarySearch(array, 0, compare), ~0);
158
assert.strictEqual(arrays.binarySearch(array, 6, compare), ~3);
159
assert.strictEqual(arrays.binarySearch(array, 70, compare), ~10);
160
});
161
162
test('binarySearch2', () => {
163
function compareTo(key: number) {
164
return (index: number) => {
165
return array[index] - key;
166
};
167
}
168
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
169
170
assert.strictEqual(arrays.binarySearch2(10, compareTo(1)), 0);
171
assert.strictEqual(arrays.binarySearch2(10, compareTo(5)), 2);
172
173
// insertion point
174
assert.strictEqual(arrays.binarySearch2(10, compareTo(0)), ~0);
175
assert.strictEqual(arrays.binarySearch2(10, compareTo(6)), ~3);
176
assert.strictEqual(arrays.binarySearch2(10, compareTo(70)), ~10);
177
assert.strictEqual(arrays.binarySearch2(2, compareTo(5)), ~2);
178
});
179
180
test('distinct', () => {
181
function compare(a: string): string {
182
return a;
183
}
184
185
assert.deepStrictEqual(arrays.distinct(['32', '4', '5'], compare), ['32', '4', '5']);
186
assert.deepStrictEqual(arrays.distinct(['32', '4', '5', '4'], compare), ['32', '4', '5']);
187
assert.deepStrictEqual(arrays.distinct(['32', 'constructor', '5', '1'], compare), ['32', 'constructor', '5', '1']);
188
assert.deepStrictEqual(arrays.distinct(['32', 'constructor', 'proto', 'proto', 'constructor'], compare), ['32', 'constructor', 'proto']);
189
assert.deepStrictEqual(arrays.distinct(['32', '4', '5', '32', '4', '5', '32', '4', '5', '5'], compare), ['32', '4', '5']);
190
});
191
192
test('top', () => {
193
const cmp = (a: number, b: number) => {
194
assert.strictEqual(typeof a, 'number', 'typeof a');
195
assert.strictEqual(typeof b, 'number', 'typeof b');
196
return a - b;
197
};
198
199
assert.deepStrictEqual(arrays.top([], cmp, 1), []);
200
assert.deepStrictEqual(arrays.top([1], cmp, 0), []);
201
assert.deepStrictEqual(arrays.top([1, 2], cmp, 1), [1]);
202
assert.deepStrictEqual(arrays.top([2, 1], cmp, 1), [1]);
203
assert.deepStrictEqual(arrays.top([1, 3, 2], cmp, 2), [1, 2]);
204
assert.deepStrictEqual(arrays.top([3, 2, 1], cmp, 3), [1, 2, 3]);
205
assert.deepStrictEqual(arrays.top([4, 6, 2, 7, 8, 3, 5, 1], cmp, 3), [1, 2, 3]);
206
});
207
208
test('topAsync', async () => {
209
const cmp = (a: number, b: number) => {
210
assert.strictEqual(typeof a, 'number', 'typeof a');
211
assert.strictEqual(typeof b, 'number', 'typeof b');
212
return a - b;
213
};
214
215
await testTopAsync(cmp, 1);
216
return testTopAsync(cmp, 2);
217
});
218
219
async function testTopAsync(cmp: any, m: number) {
220
{
221
const result = await arrays.topAsync([], cmp, 1, m);
222
assert.deepStrictEqual(result, []);
223
}
224
{
225
const result = await arrays.topAsync([1], cmp, 0, m);
226
assert.deepStrictEqual(result, []);
227
}
228
{
229
const result = await arrays.topAsync([1, 2], cmp, 1, m);
230
assert.deepStrictEqual(result, [1]);
231
}
232
{
233
const result = await arrays.topAsync([2, 1], cmp, 1, m);
234
assert.deepStrictEqual(result, [1]);
235
}
236
{
237
const result = await arrays.topAsync([1, 3, 2], cmp, 2, m);
238
assert.deepStrictEqual(result, [1, 2]);
239
}
240
{
241
const result = await arrays.topAsync([3, 2, 1], cmp, 3, m);
242
assert.deepStrictEqual(result, [1, 2, 3]);
243
}
244
{
245
const result = await arrays.topAsync([4, 6, 2, 7, 8, 3, 5, 1], cmp, 3, m);
246
assert.deepStrictEqual(result, [1, 2, 3]);
247
}
248
}
249
250
test('coalesce', () => {
251
const a: Array<number | null> = arrays.coalesce([null, 1, null, 2, 3]);
252
assert.strictEqual(a.length, 3);
253
assert.strictEqual(a[0], 1);
254
assert.strictEqual(a[1], 2);
255
assert.strictEqual(a[2], 3);
256
257
arrays.coalesce([null, 1, null, undefined, undefined, 2, 3]);
258
assert.strictEqual(a.length, 3);
259
assert.strictEqual(a[0], 1);
260
assert.strictEqual(a[1], 2);
261
assert.strictEqual(a[2], 3);
262
263
let b: number[] = [];
264
b[10] = 1;
265
b[20] = 2;
266
b[30] = 3;
267
b = arrays.coalesce(b);
268
assert.strictEqual(b.length, 3);
269
assert.strictEqual(b[0], 1);
270
assert.strictEqual(b[1], 2);
271
assert.strictEqual(b[2], 3);
272
273
let sparse: number[] = [];
274
sparse[0] = 1;
275
sparse[1] = 1;
276
sparse[17] = 1;
277
sparse[1000] = 1;
278
sparse[1001] = 1;
279
280
assert.strictEqual(sparse.length, 1002);
281
282
sparse = arrays.coalesce(sparse);
283
assert.strictEqual(sparse.length, 5);
284
});
285
286
test('coalesce - inplace', function () {
287
let a: Array<number | null> = [null, 1, null, 2, 3];
288
arrays.coalesceInPlace(a);
289
assert.strictEqual(a.length, 3);
290
assert.strictEqual(a[0], 1);
291
assert.strictEqual(a[1], 2);
292
assert.strictEqual(a[2], 3);
293
294
a = [null, 1, null, undefined!, undefined!, 2, 3];
295
arrays.coalesceInPlace(a);
296
assert.strictEqual(a.length, 3);
297
assert.strictEqual(a[0], 1);
298
assert.strictEqual(a[1], 2);
299
assert.strictEqual(a[2], 3);
300
301
const b: number[] = [];
302
b[10] = 1;
303
b[20] = 2;
304
b[30] = 3;
305
arrays.coalesceInPlace(b);
306
assert.strictEqual(b.length, 3);
307
assert.strictEqual(b[0], 1);
308
assert.strictEqual(b[1], 2);
309
assert.strictEqual(b[2], 3);
310
311
const sparse: number[] = [];
312
sparse[0] = 1;
313
sparse[1] = 1;
314
sparse[17] = 1;
315
sparse[1000] = 1;
316
sparse[1001] = 1;
317
318
assert.strictEqual(sparse.length, 1002);
319
320
arrays.coalesceInPlace(sparse);
321
assert.strictEqual(sparse.length, 5);
322
});
323
324
test('insert, remove', function () {
325
const array: string[] = [];
326
const remove = arrays.insert(array, 'foo');
327
assert.strictEqual(array[0], 'foo');
328
329
remove();
330
assert.strictEqual(array.length, 0);
331
});
332
333
test('splice', function () {
334
// negative start index, absolute value greater than the length
335
let array = [1, 2, 3, 4, 5];
336
arrays.splice(array, -6, 3, [6, 7]);
337
assert.strictEqual(array.length, 4);
338
assert.strictEqual(array[0], 6);
339
assert.strictEqual(array[1], 7);
340
assert.strictEqual(array[2], 4);
341
assert.strictEqual(array[3], 5);
342
343
// negative start index, absolute value less than the length
344
array = [1, 2, 3, 4, 5];
345
arrays.splice(array, -3, 3, [6, 7]);
346
assert.strictEqual(array.length, 4);
347
assert.strictEqual(array[0], 1);
348
assert.strictEqual(array[1], 2);
349
assert.strictEqual(array[2], 6);
350
assert.strictEqual(array[3], 7);
351
352
// Start index less than the length
353
array = [1, 2, 3, 4, 5];
354
arrays.splice(array, 3, 3, [6, 7]);
355
assert.strictEqual(array.length, 5);
356
assert.strictEqual(array[0], 1);
357
assert.strictEqual(array[1], 2);
358
assert.strictEqual(array[2], 3);
359
assert.strictEqual(array[3], 6);
360
assert.strictEqual(array[4], 7);
361
362
// Start index greater than the length
363
array = [1, 2, 3, 4, 5];
364
arrays.splice(array, 6, 3, [6, 7]);
365
assert.strictEqual(array.length, 7);
366
assert.strictEqual(array[0], 1);
367
assert.strictEqual(array[1], 2);
368
assert.strictEqual(array[2], 3);
369
assert.strictEqual(array[3], 4);
370
assert.strictEqual(array[4], 5);
371
assert.strictEqual(array[5], 6);
372
assert.strictEqual(array[6], 7);
373
});
374
375
test('findMaxBy', () => {
376
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
377
378
assert.strictEqual(
379
array.indexOf(arraysFind.findFirstMax(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
380
1
381
);
382
});
383
384
test('findLastMaxBy', () => {
385
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
386
387
assert.strictEqual(
388
array.indexOf(arraysFind.findLastMax(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
389
5
390
);
391
});
392
393
test('findMinBy', () => {
394
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
395
396
assert.strictEqual(
397
array.indexOf(arraysFind.findFirstMin(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
398
2
399
);
400
});
401
402
403
404
suite('ArrayQueue', () => {
405
suite('takeWhile/takeFromEndWhile', () => {
406
test('TakeWhile 1', () => {
407
const queue1 = new arrays.ArrayQueue([9, 8, 1, 7, 6]);
408
assert.deepStrictEqual(queue1.takeWhile(x => x > 5), [9, 8]);
409
assert.deepStrictEqual(queue1.takeWhile(x => x < 7), [1]);
410
assert.deepStrictEqual(queue1.takeWhile(x => true), [7, 6]);
411
});
412
413
test('TakeFromEndWhile 1', () => {
414
const queue1 = new arrays.ArrayQueue([9, 8, 1, 7, 6]);
415
assert.deepStrictEqual(queue1.takeFromEndWhile(x => x > 5), [7, 6]);
416
assert.deepStrictEqual(queue1.takeFromEndWhile(x => x < 2), [1]);
417
assert.deepStrictEqual(queue1.takeFromEndWhile(x => true), [9, 8]);
418
});
419
});
420
421
suite('takeWhile/takeFromEndWhile monotonous', () => {
422
function testMonotonous(array: number[], predicate: (a: number) => boolean) {
423
function normalize(arr: number[]): number[] | null {
424
if (arr.length === 0) {
425
return null;
426
}
427
return arr;
428
}
429
430
const negatedPredicate = (a: number) => !predicate(a);
431
432
{
433
const queue1 = new arrays.ArrayQueue(array);
434
assert.deepStrictEqual(queue1.takeWhile(predicate), normalize(array.filter(predicate)));
435
assert.deepStrictEqual(queue1.length, array.length - array.filter(predicate).length);
436
assert.deepStrictEqual(queue1.takeWhile(() => true), normalize(array.filter(negatedPredicate)));
437
}
438
{
439
const queue3 = new arrays.ArrayQueue(array);
440
assert.deepStrictEqual(queue3.takeFromEndWhile(negatedPredicate), normalize(array.filter(negatedPredicate)));
441
assert.deepStrictEqual(queue3.length, array.length - array.filter(negatedPredicate).length);
442
assert.deepStrictEqual(queue3.takeFromEndWhile(() => true), normalize(array.filter(predicate)));
443
}
444
}
445
446
const array = [1, 1, 1, 2, 5, 5, 7, 8, 8];
447
448
test('TakeWhile 1', () => testMonotonous(array, value => value <= 1));
449
test('TakeWhile 2', () => testMonotonous(array, value => value < 5));
450
test('TakeWhile 3', () => testMonotonous(array, value => value <= 5));
451
test('TakeWhile 4', () => testMonotonous(array, value => true));
452
test('TakeWhile 5', () => testMonotonous(array, value => false));
453
454
const array2 = [1, 1, 1, 2, 5, 5, 7, 8, 8, 9, 9, 9, 9, 10, 10];
455
456
test('TakeWhile 6', () => testMonotonous(array2, value => value < 10));
457
test('TakeWhile 7', () => testMonotonous(array2, value => value < 7));
458
test('TakeWhile 8', () => testMonotonous(array2, value => value < 5));
459
460
test('TakeWhile Empty', () => testMonotonous([], value => value <= 5));
461
});
462
});
463
});
464
465