nhb-toolbox 4.29.0 → 4.29.1
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/CHANGELOG.md +4 -0
- package/dist/cjs/string/helpers.js +5 -19
- package/dist/cjs/string/utilities.js +17 -9
- package/dist/dts/string/helpers.d.ts +2 -1
- package/dist/dts/string/utilities.d.ts +12 -4
- package/dist/dts/utils/types.d.ts +3 -1
- package/dist/esm/string/helpers.js +5 -19
- package/dist/esm/string/utilities.js +17 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
All notable changes to the package will be documented here.
|
|
6
6
|
|
|
7
|
+
## [4.29.1] - 2026-03-27
|
|
8
|
+
|
|
9
|
+
- **Updated** `getLevenshteinDistance` utility to be more *efficient* by using a *single-dimensional array* instead of a *matrix* for storing intermediate distances.
|
|
10
|
+
|
|
7
11
|
## [4.29.0] - 2026-03-26
|
|
8
12
|
|
|
9
13
|
- **Added** new *string utilities* `computeTextDiff` and `getCharacterDifferences` for computing differences between two strings at both *line* and *character* levels.
|
|
@@ -3,28 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports._calculateSimilarity = _calculateSimilarity;
|
|
4
4
|
exports._buildCharLcsTable = _buildCharLcsTable;
|
|
5
5
|
exports._getLcsIndices = _getLcsIndices;
|
|
6
|
+
const utilities_1 = require("./utilities");
|
|
6
7
|
function _calculateSimilarity(str1, str2) {
|
|
7
|
-
const len1 = str1.length;
|
|
8
|
-
const len2 = str2.length;
|
|
9
|
-
const maxLen = Math.max(len1, len2);
|
|
10
|
-
if (maxLen === 0)
|
|
11
|
-
return 1;
|
|
12
8
|
if (str1 === str2)
|
|
13
9
|
return 1;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
matrix[i][0] = i;
|
|
19
|
-
for (let j = 0; j <= len2; j++)
|
|
20
|
-
matrix[0][j] = j;
|
|
21
|
-
for (let i = 1; i <= len1; i++) {
|
|
22
|
-
for (let j = 1; j <= len2; j++) {
|
|
23
|
-
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
24
|
-
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const distance = matrix[len1][len2];
|
|
10
|
+
const maxLen = Math.max(str1.length, str2.length);
|
|
11
|
+
if (maxLen === 0)
|
|
12
|
+
return 1;
|
|
13
|
+
const distance = (0, utilities_1.getLevenshteinDistance)(str1, str2);
|
|
28
14
|
return 1 - distance / maxLen;
|
|
29
15
|
}
|
|
30
16
|
function _buildCharLcsTable(original, modified) {
|
|
@@ -6,19 +6,27 @@ const extractNumbersFromString = (input) => {
|
|
|
6
6
|
return (input.match(/\d+/g) || [])?.map(Number);
|
|
7
7
|
};
|
|
8
8
|
exports.extractNumbersFromString = extractNumbersFromString;
|
|
9
|
-
const getLevenshteinDistance = (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
9
|
+
const getLevenshteinDistance = (str1, str2) => {
|
|
10
|
+
if (str1 === str2)
|
|
11
|
+
return 0;
|
|
12
|
+
const lenA = str1?.length;
|
|
13
|
+
const lenB = str2?.length;
|
|
14
|
+
if (lenA < lenB) {
|
|
15
|
+
return (0, exports.getLevenshteinDistance)(str2, str1);
|
|
16
|
+
}
|
|
17
|
+
let prev = Array.from({ length: lenB + 1 }, (_, j) => j);
|
|
18
|
+
let curr = new Array(lenB + 1);
|
|
13
19
|
for (let i = 1; i <= lenA; i++) {
|
|
20
|
+
curr[0] = i;
|
|
14
21
|
for (let j = 1; j <= lenB; j++) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
?
|
|
18
|
-
: 1 + Math.min(
|
|
22
|
+
curr[j] =
|
|
23
|
+
str1[i - 1] === str2[j - 1]
|
|
24
|
+
? prev[j - 1]
|
|
25
|
+
: 1 + Math.min(prev[j], curr[j - 1], prev[j - 1]);
|
|
19
26
|
}
|
|
27
|
+
[prev, curr] = [curr, prev];
|
|
20
28
|
}
|
|
21
|
-
return
|
|
29
|
+
return prev[lenB];
|
|
22
30
|
};
|
|
23
31
|
exports.getLevenshteinDistance = getLevenshteinDistance;
|
|
24
32
|
function countWords(text) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TupleOf } from '../utils/types';
|
|
1
2
|
/**
|
|
2
3
|
* Calculates the similarity between two strings using the Levenshtein edit distance.
|
|
3
4
|
*
|
|
@@ -22,4 +23,4 @@ export declare function _buildCharLcsTable(original: string, modified: string):
|
|
|
22
23
|
* @param lcs The precomputed LCS table from {@link buildCharLcsTable}.
|
|
23
24
|
* @returns A tuple `[origMatched, modMatched]` — sets of matched character indices for the original and modified strings respectively.
|
|
24
25
|
*/
|
|
25
|
-
export declare function _getLcsIndices(original: string, modified: string, lcs: number[][]): Set<number
|
|
26
|
+
export declare function _getLcsIndices(original: string, modified: string, lcs: number[][]): TupleOf<Set<number>, 2>;
|
|
@@ -5,12 +5,20 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const extractNumbersFromString: (input: string) => number[];
|
|
7
7
|
/**
|
|
8
|
-
* * Computes the Levenshtein distance between two strings.
|
|
9
|
-
* @param
|
|
10
|
-
* @param
|
|
8
|
+
* * Computes the Levenshtein distance between two strings (space optimized).
|
|
9
|
+
* @param str1 - First string to compare.
|
|
10
|
+
* @param str2 - Second string to compare.
|
|
11
11
|
* @returns The Levenshtein distance between the two strings.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* - The Levenshtein distance is the minimum number of single-character edits (insertions, deletions, or substitutions) required to change one string into the other.
|
|
15
|
+
* - This implementation uses only O(min(len(a), len(b))) space by keeping only the current and previous rows of the distance matrix.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const distance = getLevenshteinDistance('kitten', 'sitting');
|
|
19
|
+
* console.log(distance); // Output: 3
|
|
12
20
|
*/
|
|
13
|
-
export declare const getLevenshteinDistance: (
|
|
21
|
+
export declare const getLevenshteinDistance: (str1: string, str2: string) => number;
|
|
14
22
|
/**
|
|
15
23
|
* * Counts the number of words in a string, supporting multiple languages and scripts.
|
|
16
24
|
*
|
|
@@ -268,6 +268,8 @@ export type ExtractRequired<T> = {
|
|
|
268
268
|
* type Role = TupleToUnion<typeof roles>; // "admin" | "user" | "guest"
|
|
269
269
|
*/
|
|
270
270
|
export type TupleToUnion<T extends readonly unknown[]> = T[number];
|
|
271
|
+
/** Internal helper type to build a tuple of length N. */
|
|
272
|
+
type $TupleOf<T, N extends number, R extends unknown[] = []> = R['length'] extends N ? R : $TupleOf<T, N, [...R, T]>;
|
|
271
273
|
/**
|
|
272
274
|
* * Creates a tuple type of a given length with elements of type T
|
|
273
275
|
*
|
|
@@ -281,7 +283,7 @@ export type TupleToUnion<T extends readonly unknown[]> = T[number];
|
|
|
281
283
|
* type FiveStrings = TupleOf<string, 5>; // [string, string, string, string, string]
|
|
282
284
|
* type EmptyTuple = TupleOf<boolean, 0>; // []
|
|
283
285
|
*/
|
|
284
|
-
export type TupleOf<T, N extends number
|
|
286
|
+
export type TupleOf<T, N extends number> = $TupleOf<T, N>;
|
|
285
287
|
/** * Build a tuple of given length (helper for type-level arithmetic). */
|
|
286
288
|
export type $BuildTuple<L extends number, T extends unknown[] = []> = T['length'] extends L ? T : $BuildTuple<L, [...T, unknown]>;
|
|
287
289
|
/** * Produce a union of numbers `From | From+1 | ... | To`. */
|
|
@@ -1,25 +1,11 @@
|
|
|
1
|
+
import { getLevenshteinDistance } from './utilities.js';
|
|
1
2
|
export function _calculateSimilarity(str1, str2) {
|
|
2
|
-
const len1 = str1.length;
|
|
3
|
-
const len2 = str2.length;
|
|
4
|
-
const maxLen = Math.max(len1, len2);
|
|
5
|
-
if (maxLen === 0)
|
|
6
|
-
return 1;
|
|
7
3
|
if (str1 === str2)
|
|
8
4
|
return 1;
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
matrix[i][0] = i;
|
|
14
|
-
for (let j = 0; j <= len2; j++)
|
|
15
|
-
matrix[0][j] = j;
|
|
16
|
-
for (let i = 1; i <= len1; i++) {
|
|
17
|
-
for (let j = 1; j <= len2; j++) {
|
|
18
|
-
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
19
|
-
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
const distance = matrix[len1][len2];
|
|
5
|
+
const maxLen = Math.max(str1.length, str2.length);
|
|
6
|
+
if (maxLen === 0)
|
|
7
|
+
return 1;
|
|
8
|
+
const distance = getLevenshteinDistance(str1, str2);
|
|
23
9
|
return 1 - distance / maxLen;
|
|
24
10
|
}
|
|
25
11
|
export function _buildCharLcsTable(original, modified) {
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
export const extractNumbersFromString = (input) => {
|
|
2
2
|
return (input.match(/\d+/g) || [])?.map(Number);
|
|
3
3
|
};
|
|
4
|
-
export const getLevenshteinDistance = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
4
|
+
export const getLevenshteinDistance = (str1, str2) => {
|
|
5
|
+
if (str1 === str2)
|
|
6
|
+
return 0;
|
|
7
|
+
const lenA = str1?.length;
|
|
8
|
+
const lenB = str2?.length;
|
|
9
|
+
if (lenA < lenB) {
|
|
10
|
+
return getLevenshteinDistance(str2, str1);
|
|
11
|
+
}
|
|
12
|
+
let prev = Array.from({ length: lenB + 1 }, (_, j) => j);
|
|
13
|
+
let curr = new Array(lenB + 1);
|
|
8
14
|
for (let i = 1; i <= lenA; i++) {
|
|
15
|
+
curr[0] = i;
|
|
9
16
|
for (let j = 1; j <= lenB; j++) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
?
|
|
13
|
-
: 1 + Math.min(
|
|
17
|
+
curr[j] =
|
|
18
|
+
str1[i - 1] === str2[j - 1]
|
|
19
|
+
? prev[j - 1]
|
|
20
|
+
: 1 + Math.min(prev[j], curr[j - 1], prev[j - 1]);
|
|
14
21
|
}
|
|
22
|
+
[prev, curr] = [curr, prev];
|
|
15
23
|
}
|
|
16
|
-
return
|
|
24
|
+
return prev[lenB];
|
|
17
25
|
};
|
|
18
26
|
export function countWords(text) {
|
|
19
27
|
return (text?.match(/\p{L}[\p{L}\p{M}\p{Pd}'’]*|\p{N}+/gu) || [])?.length;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nhb-toolbox",
|
|
3
|
-
"version": "4.29.
|
|
3
|
+
"version": "4.29.1",
|
|
4
4
|
"description": "A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|