Skip to content

Commit b11f20c

Browse files
committed
modernize, ESM, first-class TS
1 parent 26a2414 commit b11f20c

14 files changed

+3134
-79
lines changed

Diff for: .github/workflows/node.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Node
2+
on: [push, pull_request]
3+
jobs:
4+
test:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Checkout
8+
uses: actions/checkout@v4
9+
10+
- name: Setup Node
11+
uses: actions/setup-node@v4
12+
with:
13+
node-version: 20
14+
15+
- name: Install dependencies
16+
run: npm ci
17+
18+
- name: Run tests
19+
run: npm test

Diff for: .gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
quickselect.js
1+
node_modules
22
*.log

Diff for: .travis.yml

-4
This file was deleted.

Diff for: LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
ISC License
22

3-
Copyright (c) 2018, Vladimir Agafonkin
3+
Copyright (c) 2024, Vladimir Agafonkin
44

55
Permission to use, copy, modify, and/or distribute this software for any purpose
66
with or without fee is hereby granted, provided that the above copyright notice

Diff for: README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## quickselect [![Build Status](https://travis-ci.org/mourner/quickselect.svg?branch=master)](https://travis-ci.org/mourner/quickselect)
1+
## quickselect
22

33
A tiny and fast [selection algorithm](https://en.wikipedia.org/wiki/Selection_algorithm) in JavaScript
44
(specifically, [Floyd-Rivest selection](https://en.wikipedia.org/wiki/Floyd%E2%80%93Rivest_algorithm)).
@@ -19,7 +19,7 @@ The `k`-th element will have the `(k - left + 1)`-th smallest value in `[left, r
1919
Example:
2020

2121
```js
22-
var arr = [65, 28, 59, 33, 21, 56, 22, 95, 50, 12, 90, 53, 28, 77, 39];
22+
const arr = [65, 28, 59, 33, 21, 56, 22, 95, 50, 12, 90, 53, 28, 77, 39];
2323

2424
quickselect(arr, 8);
2525

Diff for: bench.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11

2-
import quickselect from './';
2+
import quickselect from './index.js';
33

4-
var N = 10000000;
5-
var arr = [];
6-
for (var i = 0; i < N; i++) arr.push(Math.random());
4+
const N = 10000000;
5+
const arr = [];
6+
for (let i = 0; i < N; i++) arr.push(Math.random());
77

88
console.time('quickselect');
9-
quickselect(arr, Math.floor(N / 2), 0, N - 1, function (a, b) {
10-
return a < b ? -1 : a > b ? 1 : 0;
11-
});
9+
quickselect(arr, Math.floor(N / 2), 0, N - 1, (a, b) => (a < b ? -1 : a > b ? 1 : 0));
1210
console.timeEnd('quickselect');

Diff for: eslint.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {default} from 'eslint-config-mourner';

Diff for: index.d.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@
22
* Rearranges items so that all items in the [left, k] are the smallest.
33
* The k-th element will have the (k - left + 1)-th smallest value in [left, right].
44
*
5-
* @param arr the array to partially sort (in place)
6-
* @param k middle index for partial sorting (as defined above)
7-
* @param left left index of the range to sort (0 by default)
8-
* @param right right index (last index of the array by default)
9-
* @param compare compare function
5+
* @template T
6+
* @param {T[]} arr the array to partially sort (in place)
7+
* @param {number} k middle index for partial sorting (as defined above)
8+
* @param {number} [left=0] left index of the range to sort
9+
* @param {number} [right=arr.length-1] right index
10+
* @param {(a: T, b: T) => number} [compare = (a, b) => a - b] compare function
1011
*/
11-
export default function quickselect<T>(
12-
arr: T[],
13-
k: number,
14-
left?: number,
15-
right?: number,
16-
compare?: (x: T, y: T) => number
17-
): void;
12+
export default function quickselect<T>(arr: T[], k: number, left?: number | undefined, right?: number | undefined, compare?: ((a: T, b: T) => number) | undefined): void;

Diff for: index.js

+37-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11

2-
export default function quickselect(arr, k, left, right, compare) {
3-
quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
4-
}
5-
6-
function quickselectStep(arr, k, left, right, compare) {
2+
/**
3+
* Rearranges items so that all items in the [left, k] are the smallest.
4+
* The k-th element will have the (k - left + 1)-th smallest value in [left, right].
5+
*
6+
* @template T
7+
* @param {T[]} arr the array to partially sort (in place)
8+
* @param {number} k middle index for partial sorting (as defined above)
9+
* @param {number} [left=0] left index of the range to sort
10+
* @param {number} [right=arr.length-1] right index
11+
* @param {(a: T, b: T) => number} [compare = (a, b) => a - b] compare function
12+
*/
13+
export default function quickselect(arr, k, left = 0, right = arr.length - 1, compare = defaultCompare) {
714

815
while (right > left) {
916
if (right - left > 600) {
10-
var n = right - left + 1;
11-
var m = k - left + 1;
12-
var z = Math.log(n);
13-
var s = 0.5 * Math.exp(2 * z / 3);
14-
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
15-
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
16-
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
17-
quickselectStep(arr, k, newLeft, newRight, compare);
17+
const n = right - left + 1;
18+
const m = k - left + 1;
19+
const z = Math.log(n);
20+
const s = 0.5 * Math.exp(2 * z / 3);
21+
const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
22+
const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
23+
const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
24+
quickselect(arr, k, newLeft, newRight, compare);
1825
}
1926

20-
var t = arr[k];
21-
var i = left;
22-
var j = right;
27+
const t = arr[k];
28+
let i = left;
29+
/** @type {number} */
30+
let j = right;
2331

2432
swap(arr, left, k);
2533
if (compare(arr[right], t) > 0) swap(arr, left, right);
@@ -43,12 +51,24 @@ function quickselectStep(arr, k, left, right, compare) {
4351
}
4452
}
4553

54+
/**
55+
* @template T
56+
* @param {T[]} arr
57+
* @param {number} i
58+
* @param {number} j
59+
*/
4660
function swap(arr, i, j) {
47-
var tmp = arr[i];
61+
const tmp = arr[i];
4862
arr[i] = arr[j];
4963
arr[j] = tmp;
5064
}
5165

66+
/**
67+
* @template T
68+
* @param {T} a
69+
* @param {T} b
70+
* @returns {number}
71+
*/
5272
function defaultCompare(a, b) {
5373
return a < b ? -1 : a > b ? 1 : 0;
5474
}

0 commit comments

Comments
 (0)