@tim-code/my-util 0.5.7 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/array.js +13 -5
- package/src/array.test.js +12 -8
package/package.json
CHANGED
package/src/array.js
CHANGED
|
@@ -221,18 +221,23 @@ function maxHeapify(heap, compare) {
|
|
|
221
221
|
* Get the first N elements of the sorted array efficiently.
|
|
222
222
|
* @template T
|
|
223
223
|
* @param {Array<T>} array
|
|
224
|
-
* @param {
|
|
225
|
-
* @param {
|
|
224
|
+
* @param {Object} $1
|
|
225
|
+
* @param {number} $1.N Number of elements to return
|
|
226
|
+
* @param {Function=} $1.compare Sort function. Default is ascending sort.
|
|
227
|
+
* @param {boolean=} $1.unsorted If true, returns the final result in heap order, not sorted order, as an optimization.
|
|
228
|
+
* Default is false.
|
|
229
|
+
* @param {boolean=} $1.force If true, will force heap-based method for small N instead of more efficient "normal" way.
|
|
230
|
+
* Default is false.
|
|
226
231
|
* @returns {Array<T>}
|
|
227
232
|
*/
|
|
228
|
-
export function sortN(array, N, compare = ascending()) {
|
|
229
|
-
if (N
|
|
233
|
+
export function sortN(array, { N, compare = ascending(), unsorted = false, force = false }) {
|
|
234
|
+
if (!(N > 0)) {
|
|
230
235
|
return []
|
|
231
236
|
}
|
|
232
237
|
if (N >= array.length) {
|
|
233
238
|
return [...array].sort(compare)
|
|
234
239
|
}
|
|
235
|
-
if (array.length <= 100 && N / array.length >= 0.1) {
|
|
240
|
+
if (!force && array.length <= 100 && N / array.length >= 0.1) {
|
|
236
241
|
// seems to be faster to do it the "normal" way in this case
|
|
237
242
|
return [...array].sort(compare).slice(0, N)
|
|
238
243
|
}
|
|
@@ -245,5 +250,8 @@ export function sortN(array, N, compare = ascending()) {
|
|
|
245
250
|
siftDown(heap, 0, compare)
|
|
246
251
|
}
|
|
247
252
|
}
|
|
253
|
+
if (unsorted) {
|
|
254
|
+
return heap
|
|
255
|
+
}
|
|
248
256
|
return heap.sort(compare)
|
|
249
257
|
}
|
package/src/array.test.js
CHANGED
|
@@ -514,38 +514,42 @@ describe("multilevel", () => {
|
|
|
514
514
|
|
|
515
515
|
describe("sortN", () => {
|
|
516
516
|
it("returns empty array when N <= 0", () => {
|
|
517
|
-
expect(sortN([1, 2, 3], 0)).toEqual([])
|
|
518
|
-
expect(sortN([1, 2, 3], -5)).toEqual([])
|
|
517
|
+
expect(sortN([1, 2, 3], { N: 0, force: true })).toEqual([])
|
|
518
|
+
expect(sortN([1, 2, 3], { N: -5, force: true })).toEqual([])
|
|
519
519
|
})
|
|
520
520
|
|
|
521
521
|
it("returns the entire array sorted when N >= array.length and does not mutate original", () => {
|
|
522
522
|
const arr = [3, 1, 2]
|
|
523
|
-
const result = sortN(arr, 10)
|
|
523
|
+
const result = sortN(arr, { N: 10, force: true })
|
|
524
524
|
expect(result).toEqual([1, 2, 3])
|
|
525
525
|
expect(arr).toEqual([3, 1, 2])
|
|
526
526
|
expect(result).not.toBe(arr)
|
|
527
527
|
})
|
|
528
528
|
|
|
529
529
|
it("returns the first N smallest elements (default ascending comparator)", () => {
|
|
530
|
-
expect(sortN([5, 1, 3, 2, 4], 3)).toEqual([1, 2, 3])
|
|
531
|
-
expect(sortN([3, 1, 3, 2, 2], 4)).toEqual([1, 2, 2, 3])
|
|
530
|
+
expect(sortN([5, 1, 3, 2, 4], { N: 3, force: true })).toEqual([1, 2, 3])
|
|
531
|
+
expect(sortN([3, 1, 3, 2, 2], { N: 4, force: true })).toEqual([1, 2, 2, 3])
|
|
532
532
|
})
|
|
533
533
|
|
|
534
534
|
it("respects a descending comparator (returns top N largest)", () => {
|
|
535
535
|
const arr = [5, 1, 3, 2, 4]
|
|
536
|
-
expect(sortN(arr, 2, descending())).toEqual([5, 4])
|
|
536
|
+
expect(sortN(arr, { N: 2, compare: descending(), force: true })).toEqual([5, 4])
|
|
537
537
|
})
|
|
538
538
|
|
|
539
539
|
it("works with key-based comparator and defers undefined/null values to the end", () => {
|
|
540
540
|
const arr = [{ v: 3 }, {}, { v: 1 }, { v: null }, { v: 2 }, { v: undefined }]
|
|
541
|
-
const out = sortN(arr, 3, ascending("v"))
|
|
541
|
+
const out = sortN(arr, { N: 3, compare: ascending("v"), force: true })
|
|
542
542
|
expect(out.map((o) => o.v)).toEqual([1, 2, 3])
|
|
543
543
|
})
|
|
544
544
|
|
|
545
545
|
it("does not mutate the original array when N < array.length", () => {
|
|
546
546
|
const arr = [5, 1, 3, 2, 4]
|
|
547
|
-
const out = sortN(arr, 3)
|
|
547
|
+
const out = sortN(arr, { N: 3, force: true })
|
|
548
548
|
expect(out).toEqual([1, 2, 3])
|
|
549
549
|
expect(arr).toEqual([5, 1, 3, 2, 4])
|
|
550
550
|
})
|
|
551
|
+
|
|
552
|
+
it("returns the first N smallest elements (default ascending comparator)", () => {
|
|
553
|
+
expect(sortN([10, 1, 7, 3, 5], { N: 3, force: true, unsorted: true })).toEqual([5, 1, 3])
|
|
554
|
+
})
|
|
551
555
|
})
|