@thi.ng/arrays 2.7.6 → 2.7.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/floyd-rivest.js CHANGED
@@ -1,69 +1,49 @@
1
1
  import { compare } from "@thi.ng/compare/compare";
2
2
  import { swap } from "./swap.js";
3
- /**
4
- * Implementation of the Floyd-Rivest selection algorithm to partially find &
5
- * sort the `k`th smallest elements in given array, according to supplied
6
- * comparator.
7
- *
8
- * @remarks
9
- * `k` is the desired index value, where `buf[k]` is the `(k+1)`th smallest
10
- * element when `left=0` (default).
11
- *
12
- * **IMPORTANT:** Mutates (partially sorts) given array such that all items in
13
- * the `[left, k]` interval are the smallest.
14
- *
15
- * @example
16
- * ```ts
17
- * floydRivest([5, 3, -1, -10, 20, 7, 0, 4, 2], 3);
18
- * // [ -10, 0, -1, 2, 3, 4, 5, 20, 7 ]
19
- * ```
20
- *
21
- * Based on pseudo-code from:
22
- * - https://en.wikipedia.org/wiki/Floyd%E2%80%93Rivest_algorithm
23
- *
24
- * @param buf
25
- * @param k
26
- * @param cmp
27
- * @param left
28
- * @param right
29
- */
30
- export const floydRivest = (buf, k = 1, cmp = compare, left = 0, right = buf.length - 1) => {
31
- while (right > left) {
32
- // constants 600 & 0.5 are from original paper
33
- if (right - left > 600) {
34
- const n = right - left + 1;
35
- const i = k - left + 1;
36
- const z = Math.log(n);
37
- const s = 0.5 * Math.exp(z * (2 / 3));
38
- const sd = 0.5 * Math.sqrt(z * s * ((n - s) / n)) * Math.sign(i - n / 2);
39
- floydRivest(buf, k, cmp, Math.max(left, (k - (i * s) / n + sd) | 0), Math.min(right, (k + ((n - i) * s) / n + sd) | 0));
40
- }
41
- const t = buf[k];
42
- let i = left;
43
- let j = right;
44
- swap(buf, left, k);
45
- if (cmp(buf[right], t) > 0)
46
- swap(buf, right, left);
47
- while (i < j) {
48
- swap(buf, i, j);
49
- i++;
50
- j--;
51
- while (compare(buf[i], t) < 0)
52
- i++;
53
- while (compare(buf[j], t) > 0)
54
- j--;
55
- }
56
- if (compare(buf[left], t) === 0) {
57
- swap(buf, left, j);
58
- }
59
- else {
60
- j++;
61
- swap(buf, j, right);
62
- }
63
- if (j <= k)
64
- left = j + 1;
65
- if (k <= j)
66
- right = j - 1;
3
+ const floydRivest = (buf, k = 1, cmp = compare, left = 0, right = buf.length - 1) => {
4
+ while (right > left) {
5
+ if (right - left > 600) {
6
+ const n = right - left + 1;
7
+ const i2 = k - left + 1;
8
+ const z = Math.log(n);
9
+ const s = 0.5 * Math.exp(z * (2 / 3));
10
+ const sd = 0.5 * Math.sqrt(z * s * ((n - s) / n)) * Math.sign(i2 - n / 2);
11
+ floydRivest(
12
+ buf,
13
+ k,
14
+ cmp,
15
+ Math.max(left, k - i2 * s / n + sd | 0),
16
+ Math.min(right, k + (n - i2) * s / n + sd | 0)
17
+ );
67
18
  }
68
- return buf;
19
+ const t = buf[k];
20
+ let i = left;
21
+ let j = right;
22
+ swap(buf, left, k);
23
+ if (cmp(buf[right], t) > 0)
24
+ swap(buf, right, left);
25
+ while (i < j) {
26
+ swap(buf, i, j);
27
+ i++;
28
+ j--;
29
+ while (compare(buf[i], t) < 0)
30
+ i++;
31
+ while (compare(buf[j], t) > 0)
32
+ j--;
33
+ }
34
+ if (compare(buf[left], t) === 0) {
35
+ swap(buf, left, j);
36
+ } else {
37
+ j++;
38
+ swap(buf, j, right);
39
+ }
40
+ if (j <= k)
41
+ left = j + 1;
42
+ if (k <= j)
43
+ right = j - 1;
44
+ }
45
+ return buf;
46
+ };
47
+ export {
48
+ floydRivest
69
49
  };
package/fuzzy-match.js CHANGED
@@ -1,40 +1,25 @@
1
1
  import { equiv as _eq } from "@thi.ng/equiv";
2
- /**
3
- * Performs a fuzzy search of `query` in `domain` and returns `true` if
4
- * successful.
5
- *
6
- * @remarks
7
- * The optional `equiv` predicate can be used to customize item equality
8
- * checking. Uses
9
- * [`equiv()`](https://docs.thi.ng/umbrella/equiv/functions/equiv.html) by
10
- * default.
11
- *
12
- * Adapted and generalized from: https://github.com/bevacqua/fufuzzyzzysearch
13
- * (MIT licensed)
14
- *
15
- * [`filterFuzzy()`](https://docs.thi.ng/umbrella/transducers/functions/filterFuzzy.html)
16
- *
17
- * @param domain - array
18
- * @param query - search value
19
- * @param equiv - equivalence predicate
20
- */
21
- export const fuzzyMatch = (domain, query, equiv = _eq) => {
22
- const nd = domain.length;
23
- const nq = query.length;
24
- if (nq > nd) {
25
- return false;
26
- }
27
- if (nq === nd) {
28
- return equiv(query, domain);
29
- }
30
- next: for (let i = 0, j = 0; i < nq; i++) {
31
- const q = query[i];
32
- while (j < nd) {
33
- if (equiv(domain[j++], q)) {
34
- continue next;
35
- }
2
+ const fuzzyMatch = (domain, query, equiv = _eq) => {
3
+ const nd = domain.length;
4
+ const nq = query.length;
5
+ if (nq > nd) {
6
+ return false;
7
+ }
8
+ if (nq === nd) {
9
+ return equiv(query, domain);
10
+ }
11
+ next:
12
+ for (let i = 0, j = 0; i < nq; i++) {
13
+ const q = query[i];
14
+ while (j < nd) {
15
+ if (equiv(domain[j++], q)) {
16
+ continue next;
36
17
  }
37
- return false;
18
+ }
19
+ return false;
38
20
  }
39
- return true;
21
+ return true;
22
+ };
23
+ export {
24
+ fuzzyMatch
40
25
  };
package/insert.js CHANGED
@@ -1,35 +1,12 @@
1
- /**
2
- * Inserts `x` into `buf` at index `i` and ensures that array length doesn't
3
- * grow beyond max `k` items (default: unbounded).
4
- *
5
- * @remarks
6
- * The function will have no effect iff `i<0` or `i>=k` or `k<1`. If
7
- * `buf.length` is larger than `k`, only the index range [i..k) will be
8
- * modified.
9
- *
10
- * In benchmarking with 4, 8, 16, 32, 64 element arrays, this function is
11
- * consistently 7-16x faster than `Array.prototype.copyWithin()` and 1.5-2x
12
- * faster than `Array.prototype.splice()` (for sizes < ~32). See
13
- * `/bench/insert.ts`
14
- *
15
- * @param buf -
16
- * @param x -
17
- * @param i -
18
- * @param k -
19
- */
20
- export const insert = (buf, x, i, k = Infinity) => i < 0 || i >= k || k < 1 ? buf : insertUnsafe(buf, x, i, k);
21
- /**
22
- * Same as {@link insert} but without any bounds/index checks.
23
- *
24
- * @param buf -
25
- * @param x -
26
- * @param i -
27
- * @param k -
28
- */
29
- export const insertUnsafe = (buf, x, i, k = Infinity) => {
30
- let j = buf.length < k ? buf.length + 1 : k;
31
- for (; --j > i;)
32
- buf[j] = buf[j - 1];
33
- buf[i] = x;
34
- return buf;
1
+ const insert = (buf, x, i, k = Infinity) => i < 0 || i >= k || k < 1 ? buf : insertUnsafe(buf, x, i, k);
2
+ const insertUnsafe = (buf, x, i, k = Infinity) => {
3
+ let j = buf.length < k ? buf.length + 1 : k;
4
+ for (; --j > i; )
5
+ buf[j] = buf[j - 1];
6
+ buf[i] = x;
7
+ return buf;
8
+ };
9
+ export {
10
+ insert,
11
+ insertUnsafe
35
12
  };
package/into.js CHANGED
@@ -1,16 +1,11 @@
1
- /**
2
- * Appends `max` items (default: all) from `src` iterable to `dest` array.
3
- * Returns `dest`.
4
- *
5
- * @param dest -
6
- * @param src -
7
- * @param max -
8
- */
9
- export const into = (dest, src, max = Infinity) => {
10
- for (let x of src) {
11
- if (--max < 0)
12
- break;
13
- dest.push(x);
14
- }
15
- return dest;
1
+ const into = (dest, src, max = Infinity) => {
2
+ for (let x of src) {
3
+ if (--max < 0)
4
+ break;
5
+ dest.push(x);
6
+ }
7
+ return dest;
8
+ };
9
+ export {
10
+ into
16
11
  };
package/is-sorted.js CHANGED
@@ -1,36 +1,14 @@
1
1
  import { compare } from "@thi.ng/compare/compare";
2
- /**
3
- * Returns true if the given array and its elements in the selected index range
4
- * (entire array, by default) are in the order defined by the given comparator
5
- * ([`compare()`](https://docs.thi.ng/umbrella/compare/functions/compare.html)
6
- * by default).
7
- *
8
- * @remarks
9
- * Always returns true, if effective index range (or array length) has less than
10
- * two elements. No bounds checking.
11
- *
12
- * @example
13
- * ```ts
14
- * isSorted([3, 2, 1])
15
- * // false
16
- *
17
- * // w/ custom comparator
18
- * isSorted([3, 2, 1], (a, b) => b - a)
19
- * // true
20
- * ```
21
- *
22
- * @param arr - array
23
- * @param cmp - comparator
24
- * @param start - start index
25
- * @param end - end index
26
- */
27
- export const isSorted = (arr, cmp = compare, start = 0, end = arr.length) => {
28
- let prev = arr[start];
29
- while (++start < end) {
30
- const curr = arr[start];
31
- if (cmp(prev, curr) > 0)
32
- return false;
33
- prev = curr;
34
- }
35
- return true;
2
+ const isSorted = (arr, cmp = compare, start = 0, end = arr.length) => {
3
+ let prev = arr[start];
4
+ while (++start < end) {
5
+ const curr = arr[start];
6
+ if (cmp(prev, curr) > 0)
7
+ return false;
8
+ prev = curr;
9
+ }
10
+ return true;
11
+ };
12
+ export {
13
+ isSorted
36
14
  };
package/iterator.js CHANGED
@@ -1,23 +1,13 @@
1
- /**
2
- * Returns iterator of nullable array w/ optional index range support
3
- * and/or reverse iteration order. The default range covers the entire
4
- * array.
5
- *
6
- * @remarks
7
- * If `start` > `end`, yields values in reverse order. No bounds
8
- * checking is performed.
9
- *
10
- * @param buf - array or null
11
- * @param start - start index
12
- * @param end - end index (excluded)
13
- */
14
- export function* arrayIterator(buf, start = 0, end) {
15
- if (!buf)
16
- return;
17
- start = start;
18
- end === undefined && (end = buf.length);
19
- const step = start <= end ? 1 : -1;
20
- for (; start !== end; start += step) {
21
- yield buf[start];
22
- }
1
+ function* arrayIterator(buf, start = 0, end) {
2
+ if (!buf)
3
+ return;
4
+ start = start;
5
+ end === void 0 && (end = buf.length);
6
+ const step = start <= end ? 1 : -1;
7
+ for (; start !== end; start += step) {
8
+ yield buf[start];
9
+ }
23
10
  }
11
+ export {
12
+ arrayIterator
13
+ };
package/levenshtein.js CHANGED
@@ -1,141 +1,95 @@
1
1
  const eqStrict = (a, b) => a === b;
2
- /**
3
- * Computes Levenshtein distance w/ optionally given `maxDist` (for
4
- * early termination, default: ∞) and equality predicate (default:
5
- * `===`). Returns 0 if both `a` and `b` are equal (based on predicate).
6
- * Returns `Infinity` if actual distance > `maxDist`.
7
- *
8
- * @remarks
9
- *
10
- * Based on:
11
- * - https://en.wikipedia.org/wiki/Levenshtein_distance
12
- * - https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm
13
- * - https://github.com/gustf/js-levenshtein/blob/develop/index.js
14
- *
15
- * @example
16
- * ```ts
17
- * levenshtein([1, 2, 3, 4, 5], [1, 2, 4, 3, 5]);
18
- * // 2
19
- *
20
- * levenshtein(
21
- * [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
22
- * [{ id: 4 }, { id: 5 }, { id: 3 }, { id: 1 }, { id: 2 }],
23
- * // max dist
24
- * 2,
25
- * // predicate
26
- * (a, b) => a.id === b.id
27
- * )
28
- * // Infinity
29
- * ```
30
- *
31
- * @param a -
32
- * @param b -
33
- * @param maxDist -
34
- * @param equiv -
35
- */
36
- export const levenshtein = (a, b, maxDist = Infinity, equiv = eqStrict) => {
37
- if (a === b) {
38
- return 0;
2
+ const levenshtein = (a, b, maxDist = Infinity, equiv = eqStrict) => {
3
+ if (a === b) {
4
+ return 0;
5
+ }
6
+ if (a.length > b.length) {
7
+ const tmp = a;
8
+ a = b;
9
+ b = tmp;
10
+ }
11
+ let la = a.length;
12
+ let lb = b.length;
13
+ while (la > 0 && equiv(a[~-la], b[~-lb])) {
14
+ la--;
15
+ lb--;
16
+ }
17
+ let offset = 0;
18
+ while (offset < la && equiv(a[offset], b[offset])) {
19
+ offset++;
20
+ }
21
+ la -= offset;
22
+ lb -= offset;
23
+ if (la === 0 || lb < 3) {
24
+ return lb;
25
+ }
26
+ let x = 0;
27
+ let y;
28
+ let minDist;
29
+ let d0;
30
+ let d1;
31
+ let d2;
32
+ let d3;
33
+ let dd;
34
+ let dy;
35
+ let ay;
36
+ let bx0;
37
+ let bx1;
38
+ let bx2;
39
+ let bx3;
40
+ const _min = (d02, d12, d22, bx, ay2) => {
41
+ return d02 < d12 || d22 < d12 ? d02 > d22 ? d22 + 1 : d02 + 1 : equiv(ay2, bx) ? d12 : d12 + 1;
42
+ };
43
+ const vector = [];
44
+ for (y = 0; y < la; y++) {
45
+ vector.push(y + 1, a[offset + y]);
46
+ }
47
+ const len = vector.length - 1;
48
+ const lb3 = lb - 3;
49
+ for (; x < lb3; ) {
50
+ bx0 = b[offset + (d0 = x)];
51
+ bx1 = b[offset + (d1 = x + 1)];
52
+ bx2 = b[offset + (d2 = x + 2)];
53
+ bx3 = b[offset + (d3 = x + 3)];
54
+ dd = x += 4;
55
+ minDist = Infinity;
56
+ for (y = 0; y < len; y += 2) {
57
+ dy = vector[y];
58
+ ay = vector[y + 1];
59
+ d0 = _min(dy, d0, d1, bx0, ay);
60
+ d1 = _min(d0, d1, d2, bx1, ay);
61
+ d2 = _min(d1, d2, d3, bx2, ay);
62
+ dd = _min(d2, d3, dd, bx3, ay);
63
+ dd < minDist && (minDist = dd);
64
+ vector[y] = dd;
65
+ d3 = d2;
66
+ d2 = d1;
67
+ d1 = d0;
68
+ d0 = dy;
39
69
  }
40
- if (a.length > b.length) {
41
- const tmp = a;
42
- a = b;
43
- b = tmp;
70
+ if (minDist > maxDist)
71
+ return Infinity;
72
+ }
73
+ for (; x < lb; ) {
74
+ bx0 = b[offset + (d0 = x)];
75
+ dd = ++x;
76
+ minDist = Infinity;
77
+ for (y = 0; y < len; y += 2) {
78
+ dy = vector[y];
79
+ vector[y] = dd = _min(dy, d0, dd, bx0, vector[y + 1]);
80
+ dd < minDist && (minDist = dd);
81
+ d0 = dy;
44
82
  }
45
- let la = a.length;
46
- let lb = b.length;
47
- while (la > 0 && equiv(a[~-la], b[~-lb])) {
48
- la--;
49
- lb--;
50
- }
51
- let offset = 0;
52
- while (offset < la && equiv(a[offset], b[offset])) {
53
- offset++;
54
- }
55
- la -= offset;
56
- lb -= offset;
57
- if (la === 0 || lb < 3) {
58
- return lb;
59
- }
60
- let x = 0;
61
- let y;
62
- let minDist;
63
- let d0;
64
- let d1;
65
- let d2;
66
- let d3;
67
- let dd;
68
- let dy;
69
- let ay;
70
- let bx0;
71
- let bx1;
72
- let bx2;
73
- let bx3;
74
- const _min = (d0, d1, d2, bx, ay) => {
75
- return d0 < d1 || d2 < d1
76
- ? d0 > d2
77
- ? d2 + 1
78
- : d0 + 1
79
- : equiv(ay, bx)
80
- ? d1
81
- : d1 + 1;
82
- };
83
- const vector = [];
84
- for (y = 0; y < la; y++) {
85
- vector.push(y + 1, a[offset + y]);
86
- }
87
- const len = vector.length - 1;
88
- const lb3 = lb - 3;
89
- for (; x < lb3;) {
90
- bx0 = b[offset + (d0 = x)];
91
- bx1 = b[offset + (d1 = x + 1)];
92
- bx2 = b[offset + (d2 = x + 2)];
93
- bx3 = b[offset + (d3 = x + 3)];
94
- dd = x += 4;
95
- minDist = Infinity;
96
- for (y = 0; y < len; y += 2) {
97
- dy = vector[y];
98
- ay = vector[y + 1];
99
- d0 = _min(dy, d0, d1, bx0, ay);
100
- d1 = _min(d0, d1, d2, bx1, ay);
101
- d2 = _min(d1, d2, d3, bx2, ay);
102
- dd = _min(d2, d3, dd, bx3, ay);
103
- dd < minDist && (minDist = dd);
104
- vector[y] = dd;
105
- d3 = d2;
106
- d2 = d1;
107
- d1 = d0;
108
- d0 = dy;
109
- }
110
- if (minDist > maxDist)
111
- return Infinity;
112
- }
113
- for (; x < lb;) {
114
- bx0 = b[offset + (d0 = x)];
115
- dd = ++x;
116
- minDist = Infinity;
117
- for (y = 0; y < len; y += 2) {
118
- dy = vector[y];
119
- vector[y] = dd = _min(dy, d0, dd, bx0, vector[y + 1]);
120
- dd < minDist && (minDist = dd);
121
- d0 = dy;
122
- }
123
- if (minDist > maxDist)
124
- return Infinity;
125
- }
126
- return dd;
83
+ if (minDist > maxDist)
84
+ return Infinity;
85
+ }
86
+ return dd;
87
+ };
88
+ const normalizedLevenshtein = (a, b, maxDist = Infinity, equiv = eqStrict) => {
89
+ const n = Math.max(a.length, b.length);
90
+ return n > 0 ? levenshtein(a, b, maxDist, equiv) / n : 0;
127
91
  };
128
- /**
129
- * Normalized version of {@link levenshtein}, i.e. the actual L-dist
130
- * divided by the length of the longest input (or `Infinity` if actual
131
- * distance > `maxDist`).
132
- *
133
- * @param a -
134
- * @param b -
135
- * @param maxDist -
136
- * @param equiv -
137
- */
138
- export const normalizedLevenshtein = (a, b, maxDist = Infinity, equiv = eqStrict) => {
139
- const n = Math.max(a.length, b.length);
140
- return n > 0 ? levenshtein(a, b, maxDist, equiv) / n : 0;
92
+ export {
93
+ levenshtein,
94
+ normalizedLevenshtein
141
95
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/arrays",
3
- "version": "2.7.6",
3
+ "version": "2.7.8",
4
4
  "description": "Array / Arraylike utilities",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,16 +35,16 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.10",
37
- "@thi.ng/checks": "^3.4.10",
38
- "@thi.ng/compare": "^2.2.6",
39
- "@thi.ng/equiv": "^2.1.35",
40
- "@thi.ng/errors": "^2.4.4",
41
- "@thi.ng/random": "^3.6.16"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/checks": "^3.4.12",
40
+ "@thi.ng/compare": "^2.2.8",
41
+ "@thi.ng/equiv": "^2.1.37",
42
+ "@thi.ng/errors": "^2.4.6",
43
+ "@thi.ng/random": "^3.6.18"
42
44
  },
43
45
  "devDependencies": {
44
46
  "@microsoft/api-extractor": "^7.38.3",
45
- "@thi.ng/testament": "^0.4.3",
47
+ "esbuild": "^0.19.8",
46
48
  "rimraf": "^5.0.5",
47
49
  "tools": "^0.0.1",
48
50
  "typedoc": "^0.25.4",
@@ -164,5 +166,5 @@
164
166
  "thi.ng": {
165
167
  "year": 2018
166
168
  },
167
- "gitHead": "04d1de79f256d7a53c6b5fd157b37f49bc88e11d\n"
169
+ "gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
168
170
  }
package/peek.js CHANGED
@@ -1,12 +1,6 @@
1
- /**
2
- * Returns first element of given array or `undefined` if array is empty.
3
- *
4
- * @param buf - array
5
- */
6
- export const first = (buf) => buf[0];
7
- /**
8
- * Returns last element of given array or `undefined` if array is empty.
9
- *
10
- * @param buf - array
11
- */
12
- export const peek = (buf) => buf[buf.length - 1];
1
+ const first = (buf) => buf[0];
2
+ const peek = (buf) => buf[buf.length - 1];
3
+ export {
4
+ first,
5
+ peek
6
+ };