atomic-fns 1.2.0 → 2.0.0

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.
Files changed (216) hide show
  1. package/README.md +397 -91
  2. package/dist/array/index.d.ts +9 -0
  3. package/dist/array/index.js +9 -0
  4. package/dist/array/list.d.ts +99 -0
  5. package/dist/array/list.js +133 -0
  6. package/dist/array/sets.d.ts +130 -0
  7. package/dist/array/sets.js +213 -0
  8. package/dist/async/index.d.ts +6 -0
  9. package/dist/async/index.js +6 -0
  10. package/dist/async/retry.d.ts +38 -0
  11. package/dist/async/retry.js +56 -0
  12. package/dist/async/sleep.d.ts +42 -0
  13. package/dist/async/sleep.js +76 -0
  14. package/dist/collections/bisect.d.ts +103 -0
  15. package/dist/collections/bisect.js +157 -0
  16. package/dist/collections/deque.d.ts +67 -97
  17. package/dist/collections/deque.js +197 -256
  18. package/dist/collections/entries.d.ts +89 -0
  19. package/dist/collections/entries.js +131 -0
  20. package/dist/collections/frozen-set.d.ts +42 -0
  21. package/dist/collections/frozen-set.js +64 -0
  22. package/dist/collections/group.d.ts +141 -0
  23. package/dist/collections/group.js +241 -0
  24. package/dist/collections/heap.d.ts +64 -0
  25. package/dist/collections/heap.js +205 -0
  26. package/dist/collections/index.d.ts +15 -623
  27. package/dist/collections/index.js +14 -844
  28. package/dist/collections/internal/arrayKeys.d.ts +19 -0
  29. package/dist/collections/internal/arrayKeys.js +83 -0
  30. package/dist/collections/internal/invariants.d.ts +4 -0
  31. package/dist/collections/internal/invariants.js +12 -0
  32. package/dist/collections/internal/iterable.d.ts +25 -0
  33. package/dist/collections/internal/iterable.js +62 -0
  34. package/dist/collections/iterate.d.ts +162 -0
  35. package/dist/collections/iterate.js +188 -0
  36. package/dist/collections/lru-cache.d.ts +58 -0
  37. package/dist/collections/lru-cache.js +164 -0
  38. package/dist/collections/order.d.ts +19 -0
  39. package/dist/collections/order.js +38 -0
  40. package/dist/collections/shape.d.ts +32 -0
  41. package/dist/collections/shape.js +86 -0
  42. package/dist/collections/sorted-map.d.ts +171 -0
  43. package/dist/collections/sorted-map.js +845 -0
  44. package/dist/collections/sorted-set.d.ts +103 -0
  45. package/dist/collections/sorted-set.js +147 -0
  46. package/dist/collections/splay-tree.d.ts +82 -0
  47. package/dist/collections/splay-tree.js +354 -0
  48. package/dist/collections/trie.d.ts +58 -0
  49. package/dist/collections/trie.js +196 -0
  50. package/dist/decimal/currency.d.ts +211 -0
  51. package/dist/decimal/currency.js +321 -0
  52. package/dist/decimal/decimal.d.ts +299 -0
  53. package/dist/decimal/decimal.js +660 -0
  54. package/dist/decimal/index.d.ts +11 -148
  55. package/dist/decimal/index.js +10 -410
  56. package/dist/decimal/internal/bits.d.ts +2 -0
  57. package/dist/decimal/internal/bits.js +7 -0
  58. package/dist/decimal/internal/echo.d.ts +4 -0
  59. package/dist/decimal/internal/echo.js +6 -0
  60. package/dist/decimal/internal/isqrt.d.ts +9 -0
  61. package/dist/decimal/internal/isqrt.js +34 -0
  62. package/dist/decimal/internal/locale.d.ts +7 -0
  63. package/dist/decimal/internal/locale.js +24 -0
  64. package/dist/decimal/internal/minor-units.d.ts +2 -0
  65. package/dist/decimal/internal/minor-units.js +33 -0
  66. package/dist/decimal/internal/pow10.d.ts +24 -0
  67. package/dist/decimal/internal/pow10.js +96 -0
  68. package/dist/encoding/base64.d.ts +39 -0
  69. package/dist/encoding/base64.js +53 -0
  70. package/dist/encoding/hex.d.ts +23 -0
  71. package/dist/encoding/hex.js +34 -0
  72. package/dist/encoding/index.d.ts +6 -0
  73. package/dist/encoding/index.js +6 -0
  74. package/dist/function/debounce.d.ts +68 -0
  75. package/dist/function/debounce.js +203 -0
  76. package/dist/function/index.d.ts +6 -0
  77. package/dist/function/index.js +6 -0
  78. package/dist/function/shared.d.ts +2 -0
  79. package/dist/function/shared.js +5 -0
  80. package/dist/function/wrap.d.ts +130 -0
  81. package/dist/function/wrap.js +113 -0
  82. package/dist/hash/digest.d.ts +18 -0
  83. package/dist/hash/digest.js +26 -0
  84. package/dist/hash/hash.d.ts +22 -0
  85. package/dist/hash/hash.js +252 -0
  86. package/dist/hash/hashString.d.ts +13 -0
  87. package/dist/hash/hashString.js +53 -0
  88. package/dist/hash/index.d.ts +8 -0
  89. package/dist/hash/index.js +8 -0
  90. package/dist/hash/stableStringify.d.ts +19 -0
  91. package/dist/hash/stableStringify.js +102 -0
  92. package/dist/id/index.d.ts +7 -0
  93. package/dist/id/index.js +7 -0
  94. package/dist/id/nanoid.d.ts +16 -0
  95. package/dist/id/nanoid.js +65 -0
  96. package/dist/id/uniqueId.d.ts +14 -0
  97. package/dist/id/uniqueId.js +20 -0
  98. package/dist/id/uuid.d.ts +25 -0
  99. package/dist/id/uuid.js +64 -0
  100. package/dist/index.d.ts +15 -8
  101. package/dist/index.js +15 -8
  102. package/dist/internal/bytes.d.ts +11 -0
  103. package/dist/internal/bytes.js +33 -0
  104. package/dist/internal/codec.d.ts +11 -0
  105. package/dist/internal/codec.js +84 -0
  106. package/dist/internal/compare.d.ts +10 -0
  107. package/dist/internal/compare.js +26 -0
  108. package/dist/internal/crypto.d.ts +5 -0
  109. package/dist/internal/crypto.js +11 -0
  110. package/dist/internal/keys.d.ts +12 -0
  111. package/dist/internal/keys.js +23 -0
  112. package/dist/internal/kind.d.ts +44 -0
  113. package/dist/internal/kind.js +139 -0
  114. package/dist/internal/sparse.d.ts +51 -0
  115. package/dist/internal/sparse.js +104 -0
  116. package/dist/internal/text.d.ts +7 -0
  117. package/dist/internal/text.js +15 -0
  118. package/dist/internal/timer.d.ts +10 -0
  119. package/dist/internal/timer.js +17 -0
  120. package/dist/internal/truncate.d.ts +10 -0
  121. package/dist/internal/truncate.js +22 -0
  122. package/dist/internal/walk.d.ts +47 -0
  123. package/dist/internal/walk.js +100 -0
  124. package/dist/is/index.d.ts +8 -0
  125. package/dist/is/index.js +8 -0
  126. package/dist/is/isArrayLike.d.ts +18 -0
  127. package/dist/is/isArrayLike.js +25 -0
  128. package/dist/is/isError.d.ts +13 -0
  129. package/dist/is/isError.js +18 -0
  130. package/dist/is/isNil.d.ts +12 -0
  131. package/dist/is/isNil.js +14 -0
  132. package/dist/is/isPlainObject.d.ts +15 -0
  133. package/dist/is/isPlainObject.js +34 -0
  134. package/dist/number/index.d.ts +7 -0
  135. package/dist/number/index.js +7 -0
  136. package/dist/number/round.d.ts +86 -0
  137. package/dist/number/round.js +130 -0
  138. package/dist/number/stats.d.ts +52 -0
  139. package/dist/number/stats.js +115 -0
  140. package/dist/object/cloneDeep.d.ts +28 -0
  141. package/dist/object/cloneDeep.js +200 -0
  142. package/dist/object/index.d.ts +14 -0
  143. package/dist/object/index.js +13 -0
  144. package/dist/object/isEqual.d.ts +64 -0
  145. package/dist/object/isEqual.js +289 -0
  146. package/dist/object/matches.d.ts +40 -0
  147. package/dist/object/matches.js +284 -0
  148. package/dist/object/merge.d.ts +66 -0
  149. package/dist/object/merge.js +272 -0
  150. package/dist/object/parsePath.d.ts +22 -0
  151. package/dist/object/parsePath.js +111 -0
  152. package/dist/object/path.d.ts +85 -0
  153. package/dist/object/path.js +208 -0
  154. package/dist/object/pick.d.ts +91 -0
  155. package/dist/object/pick.js +180 -0
  156. package/dist/object/reshape.d.ts +73 -0
  157. package/dist/object/reshape.js +144 -0
  158. package/dist/random/index.d.ts +96 -32
  159. package/dist/random/index.js +215 -53
  160. package/dist/string/case.d.ts +71 -0
  161. package/dist/string/case.js +152 -0
  162. package/dist/string/fold.d.ts +35 -0
  163. package/dist/string/fold.js +100 -0
  164. package/dist/string/index.d.ts +6 -187
  165. package/dist/string/index.js +6 -224
  166. package/dist/string/truncate.d.ts +25 -0
  167. package/dist/string/truncate.js +44 -0
  168. package/dist/string/words.d.ts +27 -0
  169. package/dist/string/words.js +241 -0
  170. package/package.json +99 -51
  171. package/dist/collections/BTree.d.ts +0 -230
  172. package/dist/collections/BTree.js +0 -1143
  173. package/dist/collections/Heap.d.ts +0 -69
  174. package/dist/collections/Heap.js +0 -181
  175. package/dist/collections/LRUCache.d.ts +0 -83
  176. package/dist/collections/LRUCache.js +0 -139
  177. package/dist/collections/SortedMap.d.ts +0 -92
  178. package/dist/collections/SortedMap.js +0 -131
  179. package/dist/collections/SortedSet.d.ts +0 -69
  180. package/dist/collections/SortedSet.js +0 -99
  181. package/dist/collections/SortedTree.d.ts +0 -103
  182. package/dist/collections/SortedTree.js +0 -142
  183. package/dist/collections/SplayTree.d.ts +0 -107
  184. package/dist/collections/SplayTree.js +0 -351
  185. package/dist/collections/Trie.d.ts +0 -42
  186. package/dist/collections/Trie.js +0 -104
  187. package/dist/collections/abc.d.ts +0 -152
  188. package/dist/collections/abc.js +0 -39
  189. package/dist/collections/frozenset.d.ts +0 -19
  190. package/dist/collections/frozenset.js +0 -33
  191. package/dist/functools/index.d.ts +0 -106
  192. package/dist/functools/index.js +0 -203
  193. package/dist/globals/index.d.ts +0 -268
  194. package/dist/globals/index.js +0 -447
  195. package/dist/i18n/currency.d.ts +0 -27
  196. package/dist/i18n/currency.js +0 -100
  197. package/dist/i18n/date/index.d.ts +0 -210
  198. package/dist/i18n/date/index.js +0 -552
  199. package/dist/i18n/date/utils.d.ts +0 -64
  200. package/dist/i18n/date/utils.js +0 -192
  201. package/dist/i18n/duration.d.ts +0 -113
  202. package/dist/i18n/duration.js +0 -398
  203. package/dist/i18n/format.d.ts +0 -34
  204. package/dist/i18n/format.js +0 -378
  205. package/dist/i18n/index.d.ts +0 -9
  206. package/dist/i18n/index.js +0 -8
  207. package/dist/itertools/index.d.ts +0 -251
  208. package/dist/itertools/index.js +0 -434
  209. package/dist/math/index.d.ts +0 -79
  210. package/dist/math/index.js +0 -81
  211. package/dist/mod.d.ts +0 -1
  212. package/dist/mod.js +0 -1
  213. package/dist/operators/index.d.ts +0 -148
  214. package/dist/operators/index.js +0 -325
  215. package/dist/types.d.ts +0 -19
  216. package/dist/types.js +0 -1
@@ -0,0 +1,131 @@
1
+ /**
2
+ * What a collection holds: `keys`, `values`, `entries`, `size`, `isEmpty`, `includes`.
3
+ */
4
+ import { isMap, isSet, mapSize, setSize, typedArrayLength } from '../internal/kind.js';
5
+ import { eachEntry } from './shape.js';
6
+ /**
7
+ * The keys of `collection`: indices of an array (holes skipped), typed array, string (one per code
8
+ * point) or other iterable, the keys of a `Map`, the members of a `Set`, and the own enumerable
9
+ * string keys of any other object. `null`, `undefined`, numbers, booleans, bigints and symbols
10
+ * have none. Other iterables are consumed to obtain positions.
11
+ * @param collection The collection to read.
12
+ * @returns A new array of keys, in iteration order.
13
+ * @example
14
+ * ```ts
15
+ * keys({ a: 1, b: 2 }) // ['a', 'b']
16
+ * keys(new Map([['x', 1]])) // ['x']
17
+ * keys('héllo') // [0, 1, 2, 3, 4]
18
+ * ```
19
+ */
20
+ export function keys(collection) {
21
+ const out = [];
22
+ eachEntry(collection, (_value, key) => {
23
+ out.push(key);
24
+ });
25
+ return out;
26
+ }
27
+ /**
28
+ * The values of `collection`, in the order {@link keys} gives their keys.
29
+ * @param collection The collection to read.
30
+ * @returns A new array of values.
31
+ * @example
32
+ * ```ts
33
+ * values({ a: 1, b: 2 }) // [1, 2]
34
+ * values(new Map([['x', 1]])) // [1]
35
+ * values('👍🏽!') // ['👍', '🏽', '!']
36
+ * ```
37
+ */
38
+ export function values(collection) {
39
+ const out = [];
40
+ eachEntry(collection, (value) => {
41
+ out.push(value);
42
+ });
43
+ return out;
44
+ }
45
+ /**
46
+ * The `[key, value]` pairs of `collection`, as `Map.prototype.entries` gives them.
47
+ * @param collection The collection to read.
48
+ * @returns A new array of pairs.
49
+ * @example
50
+ * ```ts
51
+ * entries({ a: 1 }) // [['a', 1]]
52
+ * entries(['x', 'y']) // [[0, 'x'], [1, 'y']]
53
+ * entries(new Set(['s'])) // [['s', 's']]
54
+ * ```
55
+ */
56
+ export function entries(collection) {
57
+ const out = [];
58
+ eachEntry(collection, (value, key) => {
59
+ out.push([key, value]);
60
+ });
61
+ return out;
62
+ }
63
+ /**
64
+ * How many entries `collection` has: the `size` of a `Map` or `Set`, the present elements of an
65
+ * array (holes do not count), the length of a typed array, the code points of a string, the own
66
+ * enumerable string keys of an object. An iterable that is none of these is read to its end to
67
+ * count it, so a one-shot iterator such as a generator is exhausted.
68
+ * @param collection The collection to measure.
69
+ * @returns The number of entries.
70
+ * @example
71
+ * ```ts
72
+ * size({ a: 1, b: 2 }) // 2
73
+ * size([1, , 3]) // 2
74
+ * size('👍🏽') // 2
75
+ * ```
76
+ */
77
+ export function size(collection) {
78
+ if (isMap(collection))
79
+ return mapSize(collection);
80
+ if (isSet(collection))
81
+ return setSize(collection);
82
+ if (typeof collection === 'object' && collection !== null) {
83
+ const length = typedArrayLength(collection);
84
+ if (length !== undefined)
85
+ return length;
86
+ }
87
+ let n = 0;
88
+ eachEntry(collection, () => {
89
+ n++;
90
+ });
91
+ return n;
92
+ }
93
+ /**
94
+ * True when `collection` has no entries, by the rules of {@link size}. An iterable is read only
95
+ * until its first element, and is then closed, so a one-shot iterator such as a generator has
96
+ * nothing left to give.
97
+ * @param collection The collection to test.
98
+ * @returns Whether it has no entries.
99
+ * @example
100
+ * ```ts
101
+ * isEmpty({}) // true
102
+ * isEmpty([, ,]) // true
103
+ * isEmpty(new Map([[1, 2]])) // false
104
+ * isEmpty(null) // true
105
+ * ```
106
+ */
107
+ export function isEmpty(collection) {
108
+ return !eachEntry(collection, () => true);
109
+ }
110
+ /**
111
+ * True when `collection` holds `value`, compared with SameValueZero against its values (`NaN`
112
+ * finds `NaN`, `0` finds `-0`). For a string, `value` is a substring, as
113
+ * `String.prototype.includes` reads it. An iterable is read until the first match, where it is
114
+ * closed, or to its end, so a one-shot iterator such as a generator is used up either way.
115
+ * @param collection The collection to search.
116
+ * @param value The value to look for.
117
+ * @returns Whether it is there.
118
+ * @example
119
+ * ```ts
120
+ * includes({ a: 1 }, 1) // true
121
+ * includes(new Map([['k', NaN]]), NaN) // true
122
+ * includes('hello', 'ell') // true
123
+ * ```
124
+ */
125
+ export function includes(collection, value) {
126
+ if (typeof collection === 'string')
127
+ return collection.includes(value);
128
+ if (isSet(collection))
129
+ return Set.prototype.has.call(collection, value);
130
+ return eachEntry(collection, (v) => v === value || (v !== v && value !== value));
131
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * A `Set` whose contents cannot change after construction: `add`, `delete` and `clear` throw
3
+ * `TypeError`. Membership is SameValueZero, as for any `Set`, and every read method and the ES2025
4
+ * set algebra (`union`, `intersection`, ...) are inherited; those return a plain, mutable `Set`.
5
+ * `Set.prototype.add.call(frozen, x)`, `Set.prototype.delete.call(frozen, x)` and
6
+ * `Set.prototype.clear.call(frozen)` still mutate, as with any `Set` subclass. Because it is a
7
+ * `Set`, a FrozenSet type-checks wherever a `Set` is expected, and code there that mutates it
8
+ * throws.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const primaries = new FrozenSet(['red', 'green', 'blue'])
13
+ * primaries.has('red') // true
14
+ * primaries.add('pink') // throws TypeError
15
+ * ```
16
+ */
17
+ export declare class FrozenSet<T> extends Set<T> {
18
+ /**
19
+ * Create a frozen set holding `iterable`'s values. A plain array is walked in own-element time,
20
+ * so a huge sparse array costs its elements, not its length.
21
+ * @param iterable Initial values. `null` means none.
22
+ * @throws {TypeError} when `iterable` is not iterable.
23
+ */
24
+ constructor(iterable?: Iterable<T> | null);
25
+ /**
26
+ * Rejected: a FrozenSet cannot change.
27
+ * @throws {TypeError}
28
+ */
29
+ add(_value: T): this;
30
+ /**
31
+ * Rejected: a FrozenSet cannot change.
32
+ * @throws {TypeError}
33
+ */
34
+ delete(_value: T): boolean;
35
+ /**
36
+ * Rejected: a FrozenSet cannot change.
37
+ * @throws {TypeError}
38
+ */
39
+ clear(): void;
40
+ /** `'FrozenSet'`, for `Object.prototype.toString`. */
41
+ get [Symbol.toStringTag](): string;
42
+ }
@@ -0,0 +1,64 @@
1
+ import { forEachArrayElement, iteratesAsArray } from './internal/iterable.js';
2
+ /**
3
+ * A `Set` whose contents cannot change after construction: `add`, `delete` and `clear` throw
4
+ * `TypeError`. Membership is SameValueZero, as for any `Set`, and every read method and the ES2025
5
+ * set algebra (`union`, `intersection`, ...) are inherited; those return a plain, mutable `Set`.
6
+ * `Set.prototype.add.call(frozen, x)`, `Set.prototype.delete.call(frozen, x)` and
7
+ * `Set.prototype.clear.call(frozen)` still mutate, as with any `Set` subclass. Because it is a
8
+ * `Set`, a FrozenSet type-checks wherever a `Set` is expected, and code there that mutates it
9
+ * throws.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const primaries = new FrozenSet(['red', 'green', 'blue'])
14
+ * primaries.has('red') // true
15
+ * primaries.add('pink') // throws TypeError
16
+ * ```
17
+ */
18
+ export class FrozenSet extends Set {
19
+ /**
20
+ * Create a frozen set holding `iterable`'s values. A plain array is walked in own-element time,
21
+ * so a huge sparse array costs its elements, not its length.
22
+ * @param iterable Initial values. `null` means none.
23
+ * @throws {TypeError} when `iterable` is not iterable.
24
+ */
25
+ constructor(iterable) {
26
+ super();
27
+ if (iterable == null)
28
+ return;
29
+ if (iteratesAsArray(iterable)) {
30
+ forEachArrayElement(iterable, (x) => {
31
+ super.add(x);
32
+ });
33
+ return;
34
+ }
35
+ for (const x of iterable) {
36
+ super.add(x);
37
+ }
38
+ }
39
+ /**
40
+ * Rejected: a FrozenSet cannot change.
41
+ * @throws {TypeError}
42
+ */
43
+ add(_value) {
44
+ throw new TypeError('FrozenSet is immutable');
45
+ }
46
+ /**
47
+ * Rejected: a FrozenSet cannot change.
48
+ * @throws {TypeError}
49
+ */
50
+ delete(_value) {
51
+ throw new TypeError('FrozenSet is immutable');
52
+ }
53
+ /**
54
+ * Rejected: a FrozenSet cannot change.
55
+ * @throws {TypeError}
56
+ */
57
+ clear() {
58
+ throw new TypeError('FrozenSet is immutable');
59
+ }
60
+ /** `'FrozenSet'`, for `Object.prototype.toString`. */
61
+ get [Symbol.toStringTag]() {
62
+ return 'FrozenSet';
63
+ }
64
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Grouping and ordering by key: `groupBy`, `countBy`, `keyBy`, `partition`, `sortBy`, `orderBy`,
3
+ * `minBy`, `maxBy`, `sumBy`, `meanBy`.
4
+ */
5
+ import { type Collection, type CollectionCallback, type CollectionKey, type CollectionValue } from './shape.js';
6
+ /** A key a key helper can order: a number, a bigint, a string, or `null` / `undefined` (last). */
7
+ export type SortKey = number | bigint | string | null | undefined;
8
+ /**
9
+ * The values of `collection` grouped under the key `keyOf` returns for each, in a
10
+ * `null`-prototype object, as `Object.groupBy` builds it.
11
+ * @param collection The collection to group.
12
+ * @param keyOf Returns the group key of one entry.
13
+ * @returns An object from each key to its values, in order of first appearance.
14
+ * @example
15
+ * ```ts
16
+ * groupBy([6.1, 4.2, 6.3], (n) => Math.floor(n)) // { 4: [4.2], 6: [6.1, 6.3] }
17
+ * ```
18
+ */
19
+ export declare function groupBy<C extends Collection, K extends PropertyKey>(collection: C, keyOf: CollectionCallback<C, K>): Partial<Record<K, CollectionValue<C>[]>>;
20
+ /**
21
+ * How many values of `collection` fall under each key `keyOf` returns, in a `null`-prototype
22
+ * object.
23
+ * @param collection The collection to count.
24
+ * @param keyOf Returns the key of one entry.
25
+ * @returns An object from each key to its count.
26
+ * @example
27
+ * ```ts
28
+ * countBy(['one', 'two', 'three'], (s) => s.length) // { 3: 2, 5: 1 }
29
+ * ```
30
+ */
31
+ export declare function countBy<C extends Collection, K extends PropertyKey>(collection: C, keyOf: CollectionCallback<C, K>): Partial<Record<K, number>>;
32
+ /**
33
+ * The values of `collection` under the key `keyOf` returns for each, in a `null`-prototype
34
+ * object; a later value replaces an earlier one with the same key.
35
+ * @param collection The collection to index.
36
+ * @param keyOf Returns the key of one entry.
37
+ * @returns An object from each key to the last value with it.
38
+ * @example
39
+ * ```ts
40
+ * keyBy([{ id: 'a', n: 1 }], (row) => row.id) // { a: { id: 'a', n: 1 } }
41
+ * ```
42
+ */
43
+ export declare function keyBy<C extends Collection, K extends PropertyKey>(collection: C, keyOf: CollectionCallback<C, K>): Partial<Record<K, CollectionValue<C>>>;
44
+ /**
45
+ * The values of `collection` split into those `predicate` passes and those it fails.
46
+ * @param collection The collection to split.
47
+ * @param predicate Tests one entry.
48
+ * @returns `[pass, fail]`, each in order.
49
+ * @example
50
+ * ```ts
51
+ * partition([1, 2, 3, 4], (n) => n % 2 === 0) // [[2, 4], [1, 3]]
52
+ * ```
53
+ */
54
+ export declare function partition<C extends Collection, S extends CollectionValue<C>>(collection: C, predicate: (value: CollectionValue<C>, key: CollectionKey<C>, collection: C) => value is S): [pass: S[], fail: Exclude<CollectionValue<C>, S>[]];
55
+ /** {@link partition} with a predicate that is not a type guard. */
56
+ export declare function partition<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): [pass: CollectionValue<C>[], fail: CollectionValue<C>[]];
57
+ /** `'asc'` or `'desc'`: the direction {@link orderBy} sorts one key in. */
58
+ export type SortOrder = 'asc' | 'desc';
59
+ /**
60
+ * The values of `collection` in ascending order of the keys `keyOf` returns, compared with the
61
+ * default key order: numbers and bigints by value, strings by UTF-16 code units, `null` and
62
+ * `undefined` last. The sort is stable, and several key functions break ties in turn.
63
+ * @param collection The collection to sort.
64
+ * @param keyOf One key function, or a list of them.
65
+ * @returns A new sorted array.
66
+ * @throws {RangeError} when a key is `NaN`.
67
+ * @throws {TypeError} when a key is a string against a number, or of any other type.
68
+ * @example
69
+ * ```ts
70
+ * sortBy([{ n: 2 }, { n: 1 }], (row) => row.n) // [{ n: 1 }, { n: 2 }]
71
+ * ```
72
+ */
73
+ export declare function sortBy<C extends Collection>(collection: C, keyOf: CollectionCallback<C, SortKey> | readonly CollectionCallback<C, SortKey>[]): CollectionValue<C>[];
74
+ /**
75
+ * {@link sortBy} with a direction per key: `orders[i]` is `'asc'` (the default) or `'desc'` for
76
+ * `keyOf[i]`. `null` and `undefined` keys stay last in either direction.
77
+ * @param collection The collection to sort.
78
+ * @param keyOf The key functions, in priority order.
79
+ * @param orders The direction of each key.
80
+ * @returns A new sorted array.
81
+ * @throws {TypeError} when `keyOf` or `orders` is not an array, for an unknown order or more
82
+ * orders than key functions, or for a key {@link sortBy} cannot order.
83
+ * @throws {RangeError} when a key is `NaN`.
84
+ * @example
85
+ * ```ts
86
+ * const users = [{ name: 'b', age: 1 }, { name: 'a', age: 2 }, { name: 'b', age: 3 }]
87
+ * orderBy(users, [(u) => u.name, (u) => u.age], ['asc', 'desc'])
88
+ * // [{ name: 'a', age: 2 }, { name: 'b', age: 3 }, { name: 'b', age: 1 }]
89
+ * ```
90
+ */
91
+ export declare function orderBy<C extends Collection>(collection: C, keyOf: readonly CollectionCallback<C, SortKey>[], orders?: readonly SortOrder[]): CollectionValue<C>[];
92
+ /**
93
+ * The value of `collection` with the smallest key, by the default key order; the first one on a
94
+ * tie. Entries whose key is `null` or `undefined` are skipped.
95
+ * @param collection The collection to search.
96
+ * @param keyOf Returns the key of one entry.
97
+ * @returns The value found, or `undefined` when no entry has a key.
98
+ * @throws {RangeError} for a `NaN` key; {@link sortBy} lists the `TypeError` cases.
99
+ * @example
100
+ * ```ts
101
+ * minBy([{ n: 2 }, { n: 1 }], (row) => row.n) // { n: 1 }
102
+ * ```
103
+ */
104
+ export declare function minBy<C extends Collection>(collection: C, keyOf: CollectionCallback<C, SortKey>): CollectionValue<C> | undefined;
105
+ /**
106
+ * The value of `collection` with the largest key, by the default key order; the first one on a
107
+ * tie. Entries whose key is `null` or `undefined` are skipped.
108
+ * @param collection The collection to search.
109
+ * @param keyOf Returns the key of one entry.
110
+ * @returns The value found, or `undefined` when no entry has a key.
111
+ * @throws {RangeError} for a `NaN` key; {@link sortBy} lists the `TypeError` cases.
112
+ * @example
113
+ * ```ts
114
+ * maxBy({ a: 3, b: 7 }, (n) => n) // 7
115
+ * ```
116
+ */
117
+ export declare function maxBy<C extends Collection>(collection: C, keyOf: CollectionCallback<C, SortKey>): CollectionValue<C> | undefined;
118
+ /**
119
+ * The sum of the numbers `valueOf` returns for the entries of `collection`; `0` when empty.
120
+ * @param collection The collection to add up.
121
+ * @param valueOf Returns the number of one entry.
122
+ * @returns The sum.
123
+ * @throws {TypeError} when `valueOf` returns anything but a number.
124
+ * @example
125
+ * ```ts
126
+ * sumBy([{ n: 4 }, { n: 2 }], (row) => row.n) // 6
127
+ * ```
128
+ */
129
+ export declare function sumBy<C extends Collection>(collection: C, valueOf: CollectionCallback<C, number>): number;
130
+ /**
131
+ * The mean of the numbers `valueOf` returns for the entries of `collection`; `NaN` when empty.
132
+ * @param collection The collection to average.
133
+ * @param valueOf Returns the number of one entry.
134
+ * @returns The mean.
135
+ * @throws {TypeError} when `valueOf` returns anything but a number.
136
+ * @example
137
+ * ```ts
138
+ * meanBy([{ n: 4 }, { n: 2 }], (row) => row.n) // 3
139
+ * ```
140
+ */
141
+ export declare function meanBy<C extends Collection>(collection: C, valueOf: CollectionCallback<C, number>): number;
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Grouping and ordering by key: `groupBy`, `countBy`, `keyBy`, `partition`, `sortBy`, `orderBy`,
3
+ * `minBy`, `maxBy`, `sumBy`, `meanBy`.
4
+ */
5
+ import { isNil } from '../is/isNil.js';
6
+ import { compareKeys, keyKind } from './order.js';
7
+ import { eachEntry } from './shape.js';
8
+ /**
9
+ * The values of `collection` grouped under the key `keyOf` returns for each, in a
10
+ * `null`-prototype object, as `Object.groupBy` builds it.
11
+ * @param collection The collection to group.
12
+ * @param keyOf Returns the group key of one entry.
13
+ * @returns An object from each key to its values, in order of first appearance.
14
+ * @example
15
+ * ```ts
16
+ * groupBy([6.1, 4.2, 6.3], (n) => Math.floor(n)) // { 4: [4.2], 6: [6.1, 6.3] }
17
+ * ```
18
+ */
19
+ export function groupBy(collection, keyOf) {
20
+ const fn = keyOf;
21
+ const out = Object.create(null);
22
+ eachEntry(collection, (value, key) => {
23
+ const group = fn(value, key, collection);
24
+ (out[group] ??= []).push(value);
25
+ });
26
+ return out;
27
+ }
28
+ /**
29
+ * How many values of `collection` fall under each key `keyOf` returns, in a `null`-prototype
30
+ * object.
31
+ * @param collection The collection to count.
32
+ * @param keyOf Returns the key of one entry.
33
+ * @returns An object from each key to its count.
34
+ * @example
35
+ * ```ts
36
+ * countBy(['one', 'two', 'three'], (s) => s.length) // { 3: 2, 5: 1 }
37
+ * ```
38
+ */
39
+ export function countBy(collection, keyOf) {
40
+ const fn = keyOf;
41
+ const out = Object.create(null);
42
+ eachEntry(collection, (value, key) => {
43
+ const group = fn(value, key, collection);
44
+ out[group] = (out[group] ?? 0) + 1;
45
+ });
46
+ return out;
47
+ }
48
+ /**
49
+ * The values of `collection` under the key `keyOf` returns for each, in a `null`-prototype
50
+ * object; a later value replaces an earlier one with the same key.
51
+ * @param collection The collection to index.
52
+ * @param keyOf Returns the key of one entry.
53
+ * @returns An object from each key to the last value with it.
54
+ * @example
55
+ * ```ts
56
+ * keyBy([{ id: 'a', n: 1 }], (row) => row.id) // { a: { id: 'a', n: 1 } }
57
+ * ```
58
+ */
59
+ export function keyBy(collection, keyOf) {
60
+ const fn = keyOf;
61
+ const out = Object.create(null);
62
+ eachEntry(collection, (value, key) => {
63
+ out[fn(value, key, collection)] = value;
64
+ });
65
+ return out;
66
+ }
67
+ export function partition(collection, predicate) {
68
+ const fn = predicate;
69
+ const pass = [];
70
+ const fail = [];
71
+ eachEntry(collection, (value, key) => {
72
+ ;
73
+ (fn(value, key, collection) ? pass : fail).push(value);
74
+ });
75
+ return [pass, fail];
76
+ }
77
+ function directionsOf(keyCount, orders) {
78
+ if (!Array.isArray(orders))
79
+ throw new TypeError('orders must be an array of sort orders');
80
+ if (orders.length > keyCount)
81
+ throw new TypeError(`${orders.length} sort orders given for ${keyCount} key functions`);
82
+ for (const order of orders) {
83
+ if (order !== 'asc' && order !== 'desc')
84
+ throw new TypeError(`unknown sort order ${String(order)}`);
85
+ }
86
+ return Array.from({ length: keyCount }, (_unused, i) => (orders[i] === 'desc' ? -1 : 1));
87
+ }
88
+ function sortEntries(collection, keyFns, orders) {
89
+ const directions = directionsOf(keyFns.length, orders);
90
+ const kinds = [];
91
+ const rows = [];
92
+ eachEntry(collection, (value, key) => {
93
+ const keys = keyFns.map((fn, i) => {
94
+ const k = fn(value, key, collection);
95
+ if (!isNil(k)) {
96
+ const kind = keyKind(k);
97
+ if (kinds[i] === undefined)
98
+ kinds[i] = kind;
99
+ else if (kinds[i] !== kind)
100
+ throw new TypeError('cannot order a string key against a number key');
101
+ }
102
+ return k;
103
+ });
104
+ rows.push({ value, keys });
105
+ });
106
+ rows.sort((x, y) => {
107
+ for (let i = 0; i < directions.length; i++) {
108
+ const c = compareKeys(x.keys[i], y.keys[i], directions[i]);
109
+ if (c !== 0)
110
+ return c;
111
+ }
112
+ return 0;
113
+ });
114
+ return rows.map((row) => row.value);
115
+ }
116
+ /**
117
+ * The values of `collection` in ascending order of the keys `keyOf` returns, compared with the
118
+ * default key order: numbers and bigints by value, strings by UTF-16 code units, `null` and
119
+ * `undefined` last. The sort is stable, and several key functions break ties in turn.
120
+ * @param collection The collection to sort.
121
+ * @param keyOf One key function, or a list of them.
122
+ * @returns A new sorted array.
123
+ * @throws {RangeError} when a key is `NaN`.
124
+ * @throws {TypeError} when a key is a string against a number, or of any other type.
125
+ * @example
126
+ * ```ts
127
+ * sortBy([{ n: 2 }, { n: 1 }], (row) => row.n) // [{ n: 1 }, { n: 2 }]
128
+ * ```
129
+ */
130
+ export function sortBy(collection, keyOf) {
131
+ const fns = Array.isArray(keyOf) ? keyOf : [keyOf];
132
+ return sortEntries(collection, fns, []);
133
+ }
134
+ /**
135
+ * {@link sortBy} with a direction per key: `orders[i]` is `'asc'` (the default) or `'desc'` for
136
+ * `keyOf[i]`. `null` and `undefined` keys stay last in either direction.
137
+ * @param collection The collection to sort.
138
+ * @param keyOf The key functions, in priority order.
139
+ * @param orders The direction of each key.
140
+ * @returns A new sorted array.
141
+ * @throws {TypeError} when `keyOf` or `orders` is not an array, for an unknown order or more
142
+ * orders than key functions, or for a key {@link sortBy} cannot order.
143
+ * @throws {RangeError} when a key is `NaN`.
144
+ * @example
145
+ * ```ts
146
+ * const users = [{ name: 'b', age: 1 }, { name: 'a', age: 2 }, { name: 'b', age: 3 }]
147
+ * orderBy(users, [(u) => u.name, (u) => u.age], ['asc', 'desc'])
148
+ * // [{ name: 'a', age: 2 }, { name: 'b', age: 3 }, { name: 'b', age: 1 }]
149
+ * ```
150
+ */
151
+ export function orderBy(collection, keyOf, orders = []) {
152
+ if (!Array.isArray(keyOf))
153
+ throw new TypeError('keyOf must be an array of key functions');
154
+ return sortEntries(collection, keyOf, orders);
155
+ }
156
+ function extremum(collection, keyOf, direction) {
157
+ let best;
158
+ let bestKey;
159
+ eachEntry(collection, (value, key) => {
160
+ const k = keyOf(value, key, collection);
161
+ if (isNil(k))
162
+ return;
163
+ keyKind(k);
164
+ if (bestKey === undefined || compareKeys(k, bestKey, direction) < 0) {
165
+ best = value;
166
+ bestKey = k;
167
+ }
168
+ });
169
+ return best;
170
+ }
171
+ /**
172
+ * The value of `collection` with the smallest key, by the default key order; the first one on a
173
+ * tie. Entries whose key is `null` or `undefined` are skipped.
174
+ * @param collection The collection to search.
175
+ * @param keyOf Returns the key of one entry.
176
+ * @returns The value found, or `undefined` when no entry has a key.
177
+ * @throws {RangeError} for a `NaN` key; {@link sortBy} lists the `TypeError` cases.
178
+ * @example
179
+ * ```ts
180
+ * minBy([{ n: 2 }, { n: 1 }], (row) => row.n) // { n: 1 }
181
+ * ```
182
+ */
183
+ export function minBy(collection, keyOf) {
184
+ return extremum(collection, keyOf, 1);
185
+ }
186
+ /**
187
+ * The value of `collection` with the largest key, by the default key order; the first one on a
188
+ * tie. Entries whose key is `null` or `undefined` are skipped.
189
+ * @param collection The collection to search.
190
+ * @param keyOf Returns the key of one entry.
191
+ * @returns The value found, or `undefined` when no entry has a key.
192
+ * @throws {RangeError} for a `NaN` key; {@link sortBy} lists the `TypeError` cases.
193
+ * @example
194
+ * ```ts
195
+ * maxBy({ a: 3, b: 7 }, (n) => n) // 7
196
+ * ```
197
+ */
198
+ export function maxBy(collection, keyOf) {
199
+ return extremum(collection, keyOf, -1);
200
+ }
201
+ function total(collection, valueOf) {
202
+ let sum = 0;
203
+ let count = 0;
204
+ eachEntry(collection, (value, key) => {
205
+ const n = valueOf(value, key, collection);
206
+ if (typeof n !== 'number')
207
+ throw new TypeError(`expected a number, got ${typeof n}`);
208
+ sum += n;
209
+ count++;
210
+ });
211
+ return [sum, count];
212
+ }
213
+ /**
214
+ * The sum of the numbers `valueOf` returns for the entries of `collection`; `0` when empty.
215
+ * @param collection The collection to add up.
216
+ * @param valueOf Returns the number of one entry.
217
+ * @returns The sum.
218
+ * @throws {TypeError} when `valueOf` returns anything but a number.
219
+ * @example
220
+ * ```ts
221
+ * sumBy([{ n: 4 }, { n: 2 }], (row) => row.n) // 6
222
+ * ```
223
+ */
224
+ export function sumBy(collection, valueOf) {
225
+ return total(collection, valueOf)[0];
226
+ }
227
+ /**
228
+ * The mean of the numbers `valueOf` returns for the entries of `collection`; `NaN` when empty.
229
+ * @param collection The collection to average.
230
+ * @param valueOf Returns the number of one entry.
231
+ * @returns The mean.
232
+ * @throws {TypeError} when `valueOf` returns anything but a number.
233
+ * @example
234
+ * ```ts
235
+ * meanBy([{ n: 4 }, { n: 2 }], (row) => row.n) // 3
236
+ * ```
237
+ */
238
+ export function meanBy(collection, valueOf) {
239
+ const [sum, count] = total(collection, valueOf);
240
+ return sum / count;
241
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A binary min-heap: `peek` and `pop` give the smallest item by the comparator, so a reversed
3
+ * comparator makes a max-heap. Iteration is in heap order, not sorted order. `has` and `delete`
4
+ * use SameValueZero, as `Set` does. A comparator that throws leaves the heap unchanged, and a `push`
5
+ * of several items then adds none of them. With the default comparator, items are numbers, bigints
6
+ * or strings, checked as they enter: `NaN` throws `RangeError`, and `null`, `undefined` and other
7
+ * values throw `TypeError`; pass a comparator to order them.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const heap = new Heap([5, 1, 3])
12
+ * heap.push(2)
13
+ * heap.pop() // 1
14
+ * heap.peek() // 2
15
+ * ```
16
+ */
17
+ export declare class Heap<T> {
18
+ #private;
19
+ /**
20
+ * Build a heap from `items` in linear time.
21
+ * @param items Initial items, copied. `null` means none.
22
+ * @param compareFn Comparator; the smallest item comes out first. Defaults to the primitive
23
+ * order (numbers, bigints and strings).
24
+ * @throws {TypeError} when `items` is not iterable, `compareFn` is not a function, or the default
25
+ * comparator cannot order an item.
26
+ * @throws {RangeError} when `items` is a huge sparse array, or holds `NaN` under the default
27
+ * comparator.
28
+ */
29
+ constructor(items?: Iterable<T> | null, compareFn?: ((a: T, b: T) => number) | null);
30
+ /** The number of items. */
31
+ get size(): number;
32
+ /** `'Heap'`, for `Object.prototype.toString`. */
33
+ get [Symbol.toStringTag](): string;
34
+ /**
35
+ * Add one or more items. When the comparator throws, none of them is added.
36
+ * @returns The new size.
37
+ * @throws {TypeError} when the default comparator cannot order an item.
38
+ * @throws {RangeError} when an item is `NaN` under the default comparator.
39
+ */
40
+ push(...items: T[]): number;
41
+ /** Remove and return the smallest item, or `undefined` when empty. */
42
+ pop(): T | undefined;
43
+ /** The smallest item without removing it, or `undefined` when empty. */
44
+ peek(): T | undefined;
45
+ /** Whether `item` is in the heap (SameValueZero). */
46
+ has(item: T): boolean;
47
+ /**
48
+ * Remove one occurrence of `item` (SameValueZero).
49
+ * @returns Whether it was present.
50
+ */
51
+ delete(item: T): boolean;
52
+ /** Remove every item. */
53
+ clear(): void;
54
+ /** The items, in heap order. */
55
+ values(): IteratorObject<T>;
56
+ /** The items, in heap order, as `Set.prototype.keys` gives them. */
57
+ keys(): IteratorObject<T>;
58
+ /** `[item, item]` pairs, in heap order, as `Set.prototype.entries` gives them. */
59
+ entries(): IteratorObject<[T, T]>;
60
+ /** Call `callback(item, item, heap)` for each item, in heap order. */
61
+ forEach(callback: (value: T, key: T, heap: this) => void, thisArg?: unknown): void;
62
+ /** The items, in heap order. */
63
+ [Symbol.iterator](): IteratorObject<T>;
64
+ }