@pawells/typescript-common 1.4.1 → 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 (127) hide show
  1. package/README.md +13 -12
  2. package/build/array/array-contains.d.ts +3 -0
  3. package/build/array/array-contains.d.ts.map +1 -1
  4. package/build/array/array-contains.js +4 -0
  5. package/build/array/array-contains.js.map +1 -1
  6. package/build/array/array-count-by.d.ts +2 -0
  7. package/build/array/array-count-by.d.ts.map +1 -1
  8. package/build/array/array-count-by.js +4 -1
  9. package/build/array/array-count-by.js.map +1 -1
  10. package/build/array/array-difference.d.ts +20 -9
  11. package/build/array/array-difference.d.ts.map +1 -1
  12. package/build/array/array-difference.js +25 -8
  13. package/build/array/array-difference.js.map +1 -1
  14. package/build/array/array-filter.d.ts +2 -0
  15. package/build/array/array-filter.d.ts.map +1 -1
  16. package/build/array/array-filter.js +4 -1
  17. package/build/array/array-filter.js.map +1 -1
  18. package/build/array/array-group-by.d.ts +2 -0
  19. package/build/array/array-group-by.d.ts.map +1 -1
  20. package/build/array/array-group-by.js +4 -1
  21. package/build/array/array-group-by.js.map +1 -1
  22. package/build/array/array-intersection.d.ts +20 -9
  23. package/build/array/array-intersection.d.ts.map +1 -1
  24. package/build/array/array-intersection.js +30 -12
  25. package/build/array/array-intersection.js.map +1 -1
  26. package/build/array/array-partition.d.ts +2 -0
  27. package/build/array/array-partition.d.ts.map +1 -1
  28. package/build/array/array-partition.js +4 -1
  29. package/build/array/array-partition.js.map +1 -1
  30. package/build/array/array-sample.d.ts +2 -2
  31. package/build/array/array-sample.d.ts.map +1 -1
  32. package/build/array/array-sample.js +2 -10
  33. package/build/array/array-sample.js.map +1 -1
  34. package/build/array/assert.d.ts +22 -18
  35. package/build/array/assert.d.ts.map +1 -1
  36. package/build/array/assert.js +27 -23
  37. package/build/array/assert.js.map +1 -1
  38. package/build/array/types.d.ts +11 -0
  39. package/build/array/types.d.ts.map +1 -1
  40. package/build/array/unique.d.ts +2 -0
  41. package/build/array/unique.d.ts.map +1 -1
  42. package/build/array/unique.js +4 -1
  43. package/build/array/unique.js.map +1 -1
  44. package/build/asserts/generic.d.ts +9 -0
  45. package/build/asserts/generic.d.ts.map +1 -1
  46. package/build/asserts/generic.js +30 -8
  47. package/build/asserts/generic.js.map +1 -1
  48. package/build/asserts/utils.d.ts +32 -0
  49. package/build/asserts/utils.d.ts.map +1 -1
  50. package/build/asserts/utils.js +79 -0
  51. package/build/asserts/utils.js.map +1 -1
  52. package/build/boolean/assert.d.ts.map +1 -1
  53. package/build/boolean/assert.js +2 -5
  54. package/build/boolean/assert.js.map +1 -1
  55. package/build/function/compose.d.ts +3 -2
  56. package/build/function/compose.d.ts.map +1 -1
  57. package/build/function/compose.js.map +1 -1
  58. package/build/function/debounce.d.ts +2 -1
  59. package/build/function/debounce.d.ts.map +1 -1
  60. package/build/function/debounce.js.map +1 -1
  61. package/build/function/once.d.ts +1 -0
  62. package/build/function/once.d.ts.map +1 -1
  63. package/build/function/once.js +1 -0
  64. package/build/function/once.js.map +1 -1
  65. package/build/function/throttle.d.ts +2 -1
  66. package/build/function/throttle.d.ts.map +1 -1
  67. package/build/function/throttle.js.map +1 -1
  68. package/build/index.d.ts +2 -2
  69. package/build/index.d.ts.map +1 -1
  70. package/build/index.js +1 -1
  71. package/build/index.js.map +1 -1
  72. package/build/number/assert.d.ts.map +1 -1
  73. package/build/number/assert.js +38 -42
  74. package/build/number/assert.js.map +1 -1
  75. package/build/object/clone.d.ts.map +1 -1
  76. package/build/object/clone.js +3 -0
  77. package/build/object/clone.js.map +1 -1
  78. package/build/object/equals.d.ts +1 -1
  79. package/build/object/equals.d.ts.map +1 -1
  80. package/build/object/equals.js +14 -7
  81. package/build/object/equals.js.map +1 -1
  82. package/build/object/filter-cached.js.map +1 -1
  83. package/build/object/filter.d.ts +1 -1
  84. package/build/object/filter.d.ts.map +1 -1
  85. package/build/object/filter.js +26 -65
  86. package/build/object/filter.js.map +1 -1
  87. package/build/object/hash.d.ts +1 -1
  88. package/build/object/hash.d.ts.map +1 -1
  89. package/build/object/hash.js +1 -0
  90. package/build/object/hash.js.map +1 -1
  91. package/build/object/property-paths.d.ts +2 -2
  92. package/build/object/property-paths.d.ts.map +1 -1
  93. package/build/object/property-paths.js +7 -2
  94. package/build/object/property-paths.js.map +1 -1
  95. package/build/object/security-utils.d.ts +2 -2
  96. package/build/object/security-utils.d.ts.map +1 -1
  97. package/build/object/security-utils.js.map +1 -1
  98. package/build/object/types.d.ts +1 -1
  99. package/build/object/types.d.ts.map +1 -1
  100. package/build/string/assert.d.ts.map +1 -1
  101. package/build/string/assert.js +3 -9
  102. package/build/string/assert.js.map +1 -1
  103. package/build/string/case-conversion.d.ts +53 -24
  104. package/build/string/case-conversion.d.ts.map +1 -1
  105. package/build/string/case-conversion.js +59 -29
  106. package/build/string/case-conversion.js.map +1 -1
  107. package/build/string/comparison.d.ts +20 -0
  108. package/build/string/comparison.d.ts.map +1 -0
  109. package/build/string/comparison.js +25 -0
  110. package/build/string/comparison.js.map +1 -0
  111. package/build/string/formatting.d.ts +35 -22
  112. package/build/string/formatting.d.ts.map +1 -1
  113. package/build/string/formatting.js +35 -22
  114. package/build/string/formatting.js.map +1 -1
  115. package/build/string/index.d.ts +1 -0
  116. package/build/string/index.d.ts.map +1 -1
  117. package/build/string/index.js +1 -0
  118. package/build/string/index.js.map +1 -1
  119. package/build/string/transformation.d.ts +19 -9
  120. package/build/string/transformation.d.ts.map +1 -1
  121. package/build/string/transformation.js +21 -10
  122. package/build/string/transformation.js.map +1 -1
  123. package/build/string/validation.d.ts +21 -9
  124. package/build/string/validation.d.ts.map +1 -1
  125. package/build/string/validation.js +23 -10
  126. package/build/string/validation.js.map +1 -1
  127. package/package.json +2 -2
package/README.md CHANGED
@@ -36,7 +36,7 @@ BooleanUtils.AssertBoolean(value); // throws if not a boolean
36
36
  NumberUtils.AssertNumber(value, { gte: 0, integer: true });
37
37
 
38
38
  // Direct named import (tree-shakeable)
39
- import { ArrayChunk, ObjectPick, CamelCase, Sleep, AssertString, LRUCache } from '@pawells/typescript-common';
39
+ import { ArrayChunk, ObjectPick, KebabCase, Sleep, AssertString, LRUCache } from '@pawells/typescript-common';
40
40
  ```
41
41
 
42
42
  ## Features & Patterns
@@ -140,13 +140,13 @@ ObjectFilter(order, {
140
140
  | `ObjectClone(obj)` | Deep-clone an object |
141
141
  | `ObjectEquals(a, b)` | Deep equality check |
142
142
  | `ObjectFilter(obj, filter, options?)` | Filter object by property values or predicate functions (supports dot notation, deep equality, case-insensitive matching, and predicate functions) |
143
- | `ObjectFilterCached(obj, predicate)` | Cached filter for repeated operations |
143
+ | `ObjectFilterCached(options?)` | Returns a cached filter function for repeated filtering operations with optional deep equality and case-insensitive matching |
144
144
  | `FilterObject(obj, keys)` | Keep only specified keys |
145
145
  | `ObjectPick(obj, keys)` | Pick a subset of keys |
146
146
  | `ObjectOmit(obj, keys)` | Omit specified keys |
147
147
  | `ObjectMerge(target, ...sources)` | Deep merge objects |
148
148
  | `MapObject(obj, fn)` | Map over object values |
149
- | `MapObjectCached(obj, fn)` | Cached map for repeated operations |
149
+ | `MapObjectCached(options?)` | Returns a cached map function for repeated mapping operations with optional async support |
150
150
  | `TransformObject(obj, fn)` | Transform object entries |
151
151
  | `ObjectHash(obj)` | Compute a stable hash of an object |
152
152
  | `ObjectSortKeys(obj)` | Return object with keys sorted |
@@ -169,11 +169,11 @@ ObjectFilter(order, {
169
169
  | Export | Description |
170
170
  |--------|-------------|
171
171
  | `CamelCase(str)` | Convert a string to camelCase |
172
- | `CAPITALIZE(str)` | Capitalize the first letter of a string |
173
- | `PASCAL_CASE(str)` | Convert a string to PascalCase |
174
- | `KEBAB_CASE(str)` | Convert a string to kebab-case |
175
- | `SNAKE_CASE(str)` | Convert a string to snake_case |
176
- | `SCREAMING_SNAKE_CASE(str)` | Convert a string to SCREAMING_SNAKE_CASE |
172
+ | `Capitalize(str)` | Capitalize the first letter of a string |
173
+ | `PascalCase(str)` | Convert a string to PascalCase |
174
+ | `KebabCase(str)` | Convert a string to kebab-case |
175
+ | `SnakeCase(str)` | Convert a string to snake_case |
176
+ | `ScreamingSnakeCase(str)` | Convert a string to SCREAMING_SNAKE_CASE |
177
177
  | `FormatString(template, values)` | Simple string template formatting |
178
178
  | `TruncateString(str, maxLength, ellipsis?)` | Truncate a string with ellipsis |
179
179
  | `PadString(str, length, char?, padEnd?)` | Pad a string to a specified length |
@@ -182,10 +182,11 @@ ObjectFilter(order, {
182
182
  | `Pluralize(word, count, plural?)` | Return singular or plural form based on count |
183
183
  | `WordCount(str)` | Count the number of words in a string |
184
184
  | `CountOccurrences(str, substr)` | Count non-overlapping occurrences of a substring |
185
- | `REVERSE_STRING(str)` | Reverse a string |
186
- | `SLUGIFY(str)` | Convert a string to a URL-friendly slug |
187
- | `IS_BLANK_STRING(str)` | Check if a string is empty or whitespace-only |
188
- | `IS_HEX_STRING(str)` | Check if a string is a valid hexadecimal value |
185
+ | `ReverseString(str)` | Reverse a string |
186
+ | `Slugify(str)` | Convert a string to a URL-friendly slug |
187
+ | `IsBlankString(str)` | Check if a string is empty or whitespace-only |
188
+ | `IsHexString(str)` | Check if a string is a valid hexadecimal value |
189
+ | `StringEquals(a, b, caseInsensitive?)` | Compare two strings with optional case-insensitive matching |
189
190
  | `AssertString(value, exception?)` | Assert value is a string primitive |
190
191
  | `AssertStringNotEmpty(value, exception?)` | Assert value is a non-empty, non-whitespace string |
191
192
  | `AssertStringMatches(value, regex, exception?)` | Assert string matches a regular expression |
@@ -2,6 +2,9 @@ import type { TPredicate } from './types.js';
2
2
  /**
3
3
  * Checks if an array contains at least one element that passes a predicate test.
4
4
  *
5
+ * Uses `array.some()` to check if any element satisfies the predicate condition.
6
+ * Returns false if the array is null, undefined, or empty.
7
+ *
5
8
  * @template T - The type of array elements
6
9
  * @param array - The array to check
7
10
  * @param predicate - A function that tests each element; returns `true` to signal a match
@@ -1 +1 @@
1
- {"version":3,"file":"array-contains.d.ts","sourceRoot":"","sources":["../../src/array/array-contains.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAMvF"}
1
+ {"version":3,"file":"array-contains.d.ts","sourceRoot":"","sources":["../../src/array/array-contains.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAOvF"}
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Checks if an array contains at least one element that passes a predicate test.
3
3
  *
4
+ * Uses `array.some()` to check if any element satisfies the predicate condition.
5
+ * Returns false if the array is null, undefined, or empty.
6
+ *
4
7
  * @template T - The type of array elements
5
8
  * @param array - The array to check
6
9
  * @param predicate - A function that tests each element; returns `true` to signal a match
@@ -13,6 +16,7 @@
13
16
  * ```
14
17
  */
15
18
  export function ArrayContains(array, predicate) {
19
+ // Predicate functions use array.some() / array.every() for consistency
16
20
  if (!array || array.length === 0) {
17
21
  return false;
18
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"array-contains.js","sourceRoot":"","sources":["../../src/array/array-contains.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAI,KAAmB,EAAE,SAAwB;IAC7E,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"array-contains.js","sourceRoot":"","sources":["../../src/array/array-contains.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAI,KAAmB,EAAE,SAAwB;IAC7E,uEAAuE;IACvE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC9B,CAAC"}
@@ -2,6 +2,8 @@ import type { TTransform } from './types.js';
2
2
  /**
3
3
  * Counts how many elements fall into each group defined by `keyFn`.
4
4
  *
5
+ * Returns empty object if array is null, undefined, or empty.
6
+ *
5
7
  * @template T - The type of array elements
6
8
  * @template K - The key type (string, number, or symbol)
7
9
  * @param array - The array to count
@@ -1 +1 @@
1
- {"version":3,"file":"array-count-by.d.ts","sourceRoot":"","sources":["../../src/array/array-count-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EACjE,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GACrB,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAWnB"}
1
+ {"version":3,"file":"array-count-by.d.ts","sourceRoot":"","sources":["../../src/array/array-count-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EACjE,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GACrB,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAYnB"}
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Counts how many elements fall into each group defined by `keyFn`.
3
3
  *
4
+ * Returns empty object if array is null, undefined, or empty.
5
+ *
4
6
  * @template T - The type of array elements
5
7
  * @template K - The key type (string, number, or symbol)
6
8
  * @param array - The array to count
@@ -17,7 +19,8 @@
17
19
  * ```
18
20
  */
19
21
  export function ArrayCountBy(array, keyFn) {
20
- if (array === null || array === undefined)
22
+ // Consistent null-check: early return for null/undefined arrays
23
+ if (!array)
21
24
  return {};
22
25
  const result = {};
23
26
  for (const item of array) {
@@ -1 +1 @@
1
- {"version":3,"file":"array-count-by.js","sourceRoot":"","sources":["../../src/array/array-count-by.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAC3B,KAAmB,EACnB,KAAuB;IAEvB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAuB,CAAC;IAE1E,MAAM,MAAM,GAAG,EAAuB,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,MAAM,CAAC,GAAG,CAAwB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"array-count-by.js","sourceRoot":"","sources":["../../src/array/array-count-by.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAC3B,KAAmB,EACnB,KAAuB;IAEvB,gEAAgE;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAuB,CAAC;IAE3C,MAAM,MAAM,GAAG,EAAuB,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,MAAM,CAAC,GAAG,CAAwB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -1,25 +1,36 @@
1
- import type { TEqualityComparator } from './types.js';
1
+ import type { TArrayComparisonOptions } from './types.js';
2
2
  /**
3
3
  * Returns elements present in the first array but not in the second (set difference).
4
4
  * Optimised O(n+m) using a Set when no custom comparator is provided.
5
+ * Supports custom comparators for advanced comparison logic, or deep equality checking.
5
6
  *
6
7
  * @template T - The type of array elements
7
8
  * @param array1 - The source array
8
9
  * @param array2 - Elements to exclude
9
- * @param comparator - Optional custom equality comparator
10
+ * @param options - Optional configuration
11
+ * @param options.comparator - Custom function to determine if elements are equal (optional)
12
+ * @param options.useDeepEqual - Use deep equality for comparison instead of custom comparator (optional)
10
13
  * @returns Array of elements in `array1` that are not in `array2`
11
14
  *
12
15
  * @example
13
16
  * ```typescript
17
+ * // Basic difference with primitives
14
18
  * ArrayDifference([1, 2, 3, 4], [2, 4]); // [1, 3]
15
- * ArrayDifference(
16
- * [{ id: 1 }, { id: 2 }],
17
- * [{ id: 2 }],
18
- * (a, b) => a.id === b.id,
19
- * ); // [{ id: 1 }]
19
+ *
20
+ * // Deep equality comparison with objects
21
+ * const arr1 = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
22
+ * const arr2 = [{ id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
23
+ * ArrayDifference(arr1, arr2, { useDeepEqual: true });
24
+ * // [{ id: 1, name: 'Alice' }]
25
+ *
26
+ * // Custom comparator
27
+ * ArrayDifference(arr1, arr2, {
28
+ * comparator: (a, b) => a.id === b.id
29
+ * });
30
+ * // [{ id: 1, name: 'Alice' }]
20
31
  * ```
21
32
  *
22
- * @complexity O(n+m) for primitive values, O(n*m) when a comparator is provided
33
+ * @complexity O(n+m) for primitive values, O(n*m) when a comparator or deep equality is provided
23
34
  */
24
- export declare function ArrayDifference<T>(array1: readonly T[], array2: readonly T[], comparator?: TEqualityComparator<T>): T[];
35
+ export declare function ArrayDifference<T>(array1: readonly T[], array2: readonly T[], options?: TArrayComparisonOptions<T>): T[];
25
36
  //# sourceMappingURL=array-difference.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"array-difference.d.ts","sourceRoot":"","sources":["../../src/array/array-difference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAChC,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,UAAU,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,GACjC,CAAC,EAAE,CAUL"}
1
+ {"version":3,"file":"array-difference.d.ts","sourceRoot":"","sources":["../../src/array/array-difference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAChC,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,OAAO,CAAC,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAClC,CAAC,EAAE,CAiBL"}
@@ -1,33 +1,50 @@
1
+ import { ObjectEquals } from '../object/equals.js';
1
2
  /**
2
3
  * Returns elements present in the first array but not in the second (set difference).
3
4
  * Optimised O(n+m) using a Set when no custom comparator is provided.
5
+ * Supports custom comparators for advanced comparison logic, or deep equality checking.
4
6
  *
5
7
  * @template T - The type of array elements
6
8
  * @param array1 - The source array
7
9
  * @param array2 - Elements to exclude
8
- * @param comparator - Optional custom equality comparator
10
+ * @param options - Optional configuration
11
+ * @param options.comparator - Custom function to determine if elements are equal (optional)
12
+ * @param options.useDeepEqual - Use deep equality for comparison instead of custom comparator (optional)
9
13
  * @returns Array of elements in `array1` that are not in `array2`
10
14
  *
11
15
  * @example
12
16
  * ```typescript
17
+ * // Basic difference with primitives
13
18
  * ArrayDifference([1, 2, 3, 4], [2, 4]); // [1, 3]
14
- * ArrayDifference(
15
- * [{ id: 1 }, { id: 2 }],
16
- * [{ id: 2 }],
17
- * (a, b) => a.id === b.id,
18
- * ); // [{ id: 1 }]
19
+ *
20
+ * // Deep equality comparison with objects
21
+ * const arr1 = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
22
+ * const arr2 = [{ id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
23
+ * ArrayDifference(arr1, arr2, { useDeepEqual: true });
24
+ * // [{ id: 1, name: 'Alice' }]
25
+ *
26
+ * // Custom comparator
27
+ * ArrayDifference(arr1, arr2, {
28
+ * comparator: (a, b) => a.id === b.id
29
+ * });
30
+ * // [{ id: 1, name: 'Alice' }]
19
31
  * ```
20
32
  *
21
- * @complexity O(n+m) for primitive values, O(n*m) when a comparator is provided
33
+ * @complexity O(n+m) for primitive values, O(n*m) when a comparator or deep equality is provided
22
34
  */
23
- export function ArrayDifference(array1, array2, comparator) {
35
+ export function ArrayDifference(array1, array2, options) {
24
36
  if (!array1)
25
37
  return [];
26
38
  if (!array2 || array2.length === 0)
27
39
  return [...array1];
40
+ const opts = options ?? {};
41
+ const { comparator, useDeepEqual = false } = opts;
28
42
  if (comparator) {
29
43
  return array1.filter((item) => !array2.some((other) => comparator(item, other)));
30
44
  }
45
+ if (useDeepEqual) {
46
+ return array1.filter((item) => !array2.some((other) => ObjectEquals(item, other)));
47
+ }
31
48
  const set2 = new Set(array2);
32
49
  return array1.filter((item) => !set2.has(item));
33
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"array-difference.js","sourceRoot":"","sources":["../../src/array/array-difference.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,eAAe,CAC9B,MAAoB,EACpB,MAAoB,EACpB,UAAmC;IAEnC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;IAEvD,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"array-difference.js","sourceRoot":"","sources":["../../src/array/array-difference.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,eAAe,CAC9B,MAAoB,EACpB,MAAoB,EACpB,OAAoC;IAEpC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;IAEvD,MAAM,IAAI,GAAI,OAAe,IAAI,EAAE,CAAC;IACpC,MAAM,EAAE,UAAU,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IAElD,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QAClB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC"}
@@ -3,6 +3,8 @@ import type { TPredicate } from './types.js';
3
3
  * Filters an array based on criteria that can be an object filter or a predicate function.
4
4
  * Supports nested property filtering with dot notation and array property filtering.
5
5
  *
6
+ * Returns empty array if input is null, undefined, or empty.
7
+ *
6
8
  * @param array - The array to filter
7
9
  * @param criteria - Either an object with filter criteria or a predicate function
8
10
  * @returns A new array containing only items that match the criteria
@@ -1 +1 @@
1
- {"version":3,"file":"array-filter.d.ts","sourceRoot":"","sources":["../../src/array/array-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAsC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC5B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,GACxD,CAAC,EAAE,CAeL"}
1
+ {"version":3,"file":"array-filter.d.ts","sourceRoot":"","sources":["../../src/array/array-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAsC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC5B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,GACxD,CAAC,EAAE,CAgBL"}
@@ -35,6 +35,8 @@ function matchesValue(value, filterValue) {
35
35
  * Filters an array based on criteria that can be an object filter or a predicate function.
36
36
  * Supports nested property filtering with dot notation and array property filtering.
37
37
  *
38
+ * Returns empty array if input is null, undefined, or empty.
39
+ *
38
40
  * @param array - The array to filter
39
41
  * @param criteria - Either an object with filter criteria or a predicate function
40
42
  * @returns A new array containing only items that match the criteria
@@ -66,7 +68,8 @@ function matchesValue(value, filterValue) {
66
68
  * ArrayFilter(numbers, (n) => n > 3); // [4, 5]
67
69
  */
68
70
  export function ArrayFilter(array, criteria) {
69
- if (array === null || array === undefined)
71
+ // Consistent null-check: early return for null/undefined arrays
72
+ if (!array)
70
73
  return [];
71
74
  // If criteria is a function, use it as predicate
72
75
  if (typeof criteria === 'function') {
@@ -1 +1 @@
1
- {"version":3,"file":"array-filter.js","sourceRoot":"","sources":["../../src/array/array-filter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,SAAS,cAAc,CAAC,GAAY,EAAE,IAAY;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,OAAO,GAAQ,GAAG,CAAC;IAEvB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAChE,kCAAkC;QAClC,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,WAAW;YAAE,OAAO,SAAS,CAAC;QAC1F,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAc,EAAE,WAAoB;IACzD,8DAA8D;IAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAED,wBAAwB;IACxB,OAAO,KAAK,KAAK,WAAW,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,UAAU,WAAW,CAC1B,KAAmB,EACnB,QAA0D;IAE1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAErD,iDAAiD;IACjD,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,6CAA6C;IAC7C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,EAAE;YAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5C,OAAO,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"array-filter.js","sourceRoot":"","sources":["../../src/array/array-filter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,SAAS,cAAc,CAAC,GAAY,EAAE,IAAY;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,OAAO,GAAQ,GAAG,CAAC;IAEvB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAChE,kCAAkC;QAClC,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,WAAW;YAAE,OAAO,SAAS,CAAC;QAC1F,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAc,EAAE,WAAoB;IACzD,8DAA8D;IAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAED,wBAAwB;IACxB,OAAO,KAAK,KAAK,WAAW,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,WAAW,CAC1B,KAAmB,EACnB,QAA0D;IAE1D,gEAAgE;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,iDAAiD;IACjD,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,6CAA6C;IAC7C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,EAAE;YAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5C,OAAO,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -2,6 +2,8 @@ import type { TTransform } from './types.js';
2
2
  /**
3
3
  * Groups array elements by a key generated by a provided function.
4
4
  *
5
+ * Returns empty object if array is null, undefined, or empty.
6
+ *
5
7
  * @template T - The type of array elements
6
8
  * @template K - The key type (string, number, or symbol)
7
9
  * @param array - The array to group
@@ -1 +1 @@
1
- {"version":3,"file":"array-group-by.d.ts","sourceRoot":"","sources":["../../src/array/array-group-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAahI"}
1
+ {"version":3,"file":"array-group-by.d.ts","sourceRoot":"","sources":["../../src/array/array-group-by.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAchI"}
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Groups array elements by a key generated by a provided function.
3
3
  *
4
+ * Returns empty object if array is null, undefined, or empty.
5
+ *
4
6
  * @template T - The type of array elements
5
7
  * @template K - The key type (string, number, or symbol)
6
8
  * @param array - The array to group
@@ -18,7 +20,8 @@
18
20
  * ```
19
21
  */
20
22
  export function ArrayGroupBy(array, keyFn) {
21
- if (array === null || array === undefined) {
23
+ // Consistent null-check: early return for null/undefined arrays
24
+ if (!array) {
22
25
  return {};
23
26
  }
24
27
  return array.reduce((acc, item) => {
@@ -1 +1 @@
1
- {"version":3,"file":"array-group-by.js","sourceRoot":"","sources":["../../src/array/array-group-by.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAwC,KAAmB,EAAE,KAAuB;IAC/G,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO,EAAoB,CAAC;IAC7B,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACf,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACf,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,GAAG,CAAC;IACZ,CAAC,EAAE,EAAoB,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"array-group-by.js","sourceRoot":"","sources":["../../src/array/array-group-by.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,YAAY,CAAwC,KAAmB,EAAE,KAAuB;IAC/G,gEAAgE;IAChE,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,OAAO,EAAoB,CAAC;IAC7B,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACf,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACf,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,GAAG,CAAC;IACZ,CAAC,EAAE,EAAoB,CAAC,CAAC;AAC1B,CAAC"}
@@ -1,25 +1,36 @@
1
- import type { TEqualityComparator } from './types.js';
1
+ import type { TArrayComparisonOptions } from './types.js';
2
2
  /**
3
3
  * Returns the intersection of two arrays (elements present in both)
4
- * Optimized O(n+m) complexity using Set-based approach
4
+ * Optimized O(n+m) complexity using Set-based approach.
5
+ * Supports custom comparators for advanced comparison logic, or deep equality checking.
5
6
  *
6
7
  * @template T - The type of array elements
7
8
  * @param array1 - First array
8
9
  * @param array2 - Second array
9
- * @param comparator - Optional custom equality comparator
10
+ * @param options - Optional configuration
11
+ * @param options.comparator - Custom function to determine if elements are equal (optional)
12
+ * @param options.useDeepEqual - Use deep equality for comparison instead of custom comparator (optional)
10
13
  * @returns Array containing elements present in both arrays
11
14
  *
12
15
  * @example
13
16
  * ```typescript
17
+ * // Basic intersection with primitives
14
18
  * ArrayIntersection([1, 2, 3], [2, 3, 4]); // [2, 3]
15
- * ArrayIntersection(
16
- * [{id: 1}, {id: 2}],
17
- * [{id: 2}, {id: 3}],
18
- * (a, b) => a.id === b.id
19
- * ); // [{id: 2}]
19
+ *
20
+ * // Deep equality comparison with objects
21
+ * const arr1 = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
22
+ * const arr2 = [{ id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
23
+ * ArrayIntersection(arr1, arr2, { useDeepEqual: true });
24
+ * // [{ id: 2, name: 'Bob' }]
25
+ *
26
+ * // Custom comparator
27
+ * ArrayIntersection(arr1, arr2, {
28
+ * comparator: (a, b) => a.id === b.id
29
+ * });
30
+ * // [{ id: 2, name: 'Bob' }]
20
31
  * ```
21
32
  *
22
33
  * @complexity O(n+m) where n and m are array lengths
23
34
  */
24
- export declare function ArrayIntersection<T>(array1: readonly T[], array2: readonly T[], comparator?: TEqualityComparator<T>): T[];
35
+ export declare function ArrayIntersection<T>(array1: readonly T[], array2: readonly T[], options?: TArrayComparisonOptions<T>): T[];
25
36
  //# sourceMappingURL=array-intersection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"array-intersection.d.ts","sourceRoot":"","sources":["../../src/array/array-intersection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAClC,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,UAAU,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,GACjC,CAAC,EAAE,CAoBL"}
1
+ {"version":3,"file":"array-intersection.d.ts","sourceRoot":"","sources":["../../src/array/array-intersection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAClC,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,OAAO,CAAC,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAClC,CAAC,EAAE,CA8BL"}
@@ -1,39 +1,57 @@
1
+ import { ObjectEquals } from '../object/equals.js';
1
2
  /**
2
3
  * Returns the intersection of two arrays (elements present in both)
3
- * Optimized O(n+m) complexity using Set-based approach
4
+ * Optimized O(n+m) complexity using Set-based approach.
5
+ * Supports custom comparators for advanced comparison logic, or deep equality checking.
4
6
  *
5
7
  * @template T - The type of array elements
6
8
  * @param array1 - First array
7
9
  * @param array2 - Second array
8
- * @param comparator - Optional custom equality comparator
10
+ * @param options - Optional configuration
11
+ * @param options.comparator - Custom function to determine if elements are equal (optional)
12
+ * @param options.useDeepEqual - Use deep equality for comparison instead of custom comparator (optional)
9
13
  * @returns Array containing elements present in both arrays
10
14
  *
11
15
  * @example
12
16
  * ```typescript
17
+ * // Basic intersection with primitives
13
18
  * ArrayIntersection([1, 2, 3], [2, 3, 4]); // [2, 3]
14
- * ArrayIntersection(
15
- * [{id: 1}, {id: 2}],
16
- * [{id: 2}, {id: 3}],
17
- * (a, b) => a.id === b.id
18
- * ); // [{id: 2}]
19
+ *
20
+ * // Deep equality comparison with objects
21
+ * const arr1 = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
22
+ * const arr2 = [{ id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
23
+ * ArrayIntersection(arr1, arr2, { useDeepEqual: true });
24
+ * // [{ id: 2, name: 'Bob' }]
25
+ *
26
+ * // Custom comparator
27
+ * ArrayIntersection(arr1, arr2, {
28
+ * comparator: (a, b) => a.id === b.id
29
+ * });
30
+ * // [{ id: 2, name: 'Bob' }]
19
31
  * ```
20
32
  *
21
33
  * @complexity O(n+m) where n and m are array lengths
22
34
  */
23
- export function ArrayIntersection(array1, array2, comparator) {
35
+ export function ArrayIntersection(array1, array2, options) {
24
36
  if (!array1 || !array2) {
25
37
  return [];
26
38
  }
27
- // If no custom comparator, use Set for O(n+m) performance
28
- if (!comparator) {
39
+ const opts = options ?? {};
40
+ const { comparator, useDeepEqual = false } = opts;
41
+ // If no custom comparator and no deep equality, use Set for O(n+m) performance
42
+ if (!comparator && !useDeepEqual) {
29
43
  const set2 = new Set(array2);
30
44
  return array1.filter(item => set2.has(item));
31
45
  }
32
- // With custom comparator, still optimize by checking smaller array
46
+ // With custom comparator or deep equality, optimize by checking smaller array
33
47
  // This reduces comparisons from n*m to min(n,m)*max(n,m)
34
48
  const [smaller, larger] = array1.length <= array2.length
35
49
  ? [array1, array2]
36
50
  : [array2, array1];
37
- return smaller.filter(item => larger.some(otherItem => comparator(item, otherItem)));
51
+ if (comparator) {
52
+ return smaller.filter(item => larger.some(otherItem => comparator(item, otherItem)));
53
+ }
54
+ // Use deep equality
55
+ return smaller.filter(item => larger.some(otherItem => ObjectEquals(item, otherItem)));
38
56
  }
39
57
  //# sourceMappingURL=array-intersection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"array-intersection.js","sourceRoot":"","sources":["../../src/array/array-intersection.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,iBAAiB,CAChC,MAAoB,EACpB,MAAoB,EACpB,UAAmC;IAEnC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,mEAAmE;IACnE,yDAAyD;IACzD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;QACvD,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC;QAClB,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEpB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CACrD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"array-intersection.js","sourceRoot":"","sources":["../../src/array/array-intersection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,iBAAiB,CAChC,MAAoB,EACpB,MAAoB,EACpB,OAAoC;IAEpC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,IAAI,GAAI,OAAe,IAAI,EAAE,CAAC;IACpC,MAAM,EAAE,UAAU,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IAElD,+EAA+E;IAC/E,IAAI,CAAC,UAAU,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,8EAA8E;IAC9E,yDAAyD;IACzD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;QACvD,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC;QAClB,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEpB,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CACrD,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CACvD,CAAC;AACH,CAAC"}
@@ -2,6 +2,8 @@ import type { TPredicate } from './types.js';
2
2
  /**
3
3
  * Splits an array into two groups: elements that satisfy the predicate and those that do not.
4
4
  *
5
+ * Returns `[[], []]` if array is null, undefined, or empty.
6
+ *
5
7
  * @template T - The type of array elements
6
8
  * @param array - The array to partition
7
9
  * @param predicate - The condition to test each element against
@@ -1 +1 @@
1
- {"version":3,"file":"array-partition.d.ts","sourceRoot":"","sources":["../../src/array/array-partition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAe3F"}
1
+ {"version":3,"file":"array-partition.d.ts","sourceRoot":"","sources":["../../src/array/array-partition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAgB3F"}
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Splits an array into two groups: elements that satisfy the predicate and those that do not.
3
3
  *
4
+ * Returns `[[], []]` if array is null, undefined, or empty.
5
+ *
4
6
  * @template T - The type of array elements
5
7
  * @param array - The array to partition
6
8
  * @param predicate - The condition to test each element against
@@ -15,7 +17,8 @@
15
17
  * ```
16
18
  */
17
19
  export function ArrayPartition(array, predicate) {
18
- if (array === null || array === undefined)
20
+ // Consistent null-check: early return for null/undefined arrays
21
+ if (!array)
19
22
  return [[], []];
20
23
  const matches = [];
21
24
  const rest = [];
@@ -1 +1 @@
1
- {"version":3,"file":"array-partition.js","sourceRoot":"","sources":["../../src/array/array-partition.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAI,KAAmB,EAAE,SAAwB;IAC9E,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAE3D,MAAM,OAAO,GAAQ,EAAE,CAAC;IACxB,MAAM,IAAI,GAAQ,EAAE,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACF,CAAC;IAED,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"array-partition.js","sourceRoot":"","sources":["../../src/array/array-partition.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,cAAc,CAAI,KAAmB,EAAE,SAAwB;IAC9E,gEAAgE;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAE5B,MAAM,OAAO,GAAQ,EAAE,CAAC;IACxB,MAAM,IAAI,GAAQ,EAAE,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACF,CAAC;IAED,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC"}
@@ -9,10 +9,10 @@
9
9
  * @example
10
10
  * ```typescript
11
11
  * ArraySample([1, 2, 3, 4, 5]); // e.g. 3
12
- * ArraySample([1, 2, 3], () => 0.5); // deterministic with custom RNG
12
+ * ArraySample([1, 2, 3], undefined, () => 0.5); // deterministic with custom RNG
13
13
  * ```
14
14
  */
15
- export declare function ArraySample<T>(array: readonly T[], random?: () => number): T | undefined;
15
+ export declare function ArraySample<T>(array: readonly T[]): T | undefined;
16
16
  /**
17
17
  * Returns `n` unique random elements from an array (without replacement).
18
18
  * If `n` exceeds the array length, all elements are returned in random order.
@@ -1 +1 @@
1
- {"version":3,"file":"array-sample.d.ts","sourceRoot":"","sources":["../../src/array/array-sample.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;AAE1F;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,MAAM,GAAG,CAAC,EAAE,CAAC"}
1
+ {"version":3,"file":"array-sample.d.ts","sourceRoot":"","sources":["../../src/array/array-sample.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;AAEnE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,MAAM,GAAG,CAAC,EAAE,CAAC"}
@@ -1,14 +1,6 @@
1
1
  export function ArraySample(array, n, random) {
2
- // Handle overload where second argument is RNG function
3
- let sampleCount;
4
- let rng = random ?? Math.random;
5
- if (typeof n === 'function') {
6
- rng = n;
7
- sampleCount = undefined;
8
- }
9
- else {
10
- sampleCount = n;
11
- }
2
+ const sampleCount = n;
3
+ const rng = random ?? Math.random;
12
4
  if (!array || array.length === 0) {
13
5
  return sampleCount !== undefined ? [] : undefined;
14
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"array-sample.js","sourceRoot":"","sources":["../../src/array/array-sample.ts"],"names":[],"mappings":"AAkCA,MAAM,UAAU,WAAW,CAAI,KAAmB,EAAE,CAA2B,EAAE,MAAqB;IACrG,wDAAwD;IACxD,IAAI,WAA+B,CAAC;IACpC,IAAI,GAAG,GAAiB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAE9C,IAAI,OAAO,CAAC,KAAK,UAAU,EAAE,CAAC;QAC7B,GAAG,GAAG,CAAC,CAAC;QACR,WAAW,GAAG,SAAS,CAAC;IACzB,CAAC;SAAM,CAAC;QACP,WAAW,GAAG,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACnD,CAAC;IAED,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,iDAAiD;IACjD,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAM,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAM,CAAC;QACvB,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"array-sample.js","sourceRoot":"","sources":["../../src/array/array-sample.ts"],"names":[],"mappings":"AAkCA,MAAM,UAAU,WAAW,CAAI,KAAmB,EAAE,CAAU,EAAE,MAAqB;IACpF,MAAM,WAAW,GAAG,CAAC,CAAC;IACtB,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAElC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACnD,CAAC;IAED,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,iDAAiD;IACjD,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAM,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAM,CAAC;QACvB,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC"}