cmpstr 2.0.2 → 3.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.
- package/LICENSE +21 -21
- package/README.md +75 -499
- package/dist/CmpStr.esm.js +4863 -0
- package/dist/CmpStr.esm.js.map +1 -0
- package/dist/CmpStr.esm.min.js +8 -0
- package/dist/CmpStr.esm.min.js.map +1 -0
- package/dist/CmpStr.umd.js +4875 -0
- package/dist/CmpStr.umd.js.map +1 -0
- package/dist/CmpStr.umd.min.js +8 -0
- package/dist/CmpStr.umd.min.js.map +1 -0
- package/dist/cjs/CmpStr.js +663 -0
- package/dist/cjs/CmpStr.js.map +1 -0
- package/dist/cjs/CmpStrAsync.js +336 -0
- package/dist/cjs/CmpStrAsync.js.map +1 -0
- package/dist/cjs/index.js +15 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/metric/Cosine.js +101 -0
- package/dist/cjs/metric/Cosine.js.map +1 -0
- package/dist/cjs/metric/DamerauLevenshtein.js +110 -0
- package/dist/cjs/metric/DamerauLevenshtein.js.map +1 -0
- package/dist/cjs/metric/DiceSorensen.js +91 -0
- package/dist/cjs/metric/DiceSorensen.js.map +1 -0
- package/dist/cjs/metric/Hamming.js +82 -0
- package/dist/cjs/metric/Hamming.js.map +1 -0
- package/dist/cjs/metric/Jaccard.js +76 -0
- package/dist/cjs/metric/Jaccard.js.map +1 -0
- package/dist/cjs/metric/JaroWinkler.js +114 -0
- package/dist/cjs/metric/JaroWinkler.js.map +1 -0
- package/dist/cjs/metric/LCS.js +89 -0
- package/dist/cjs/metric/LCS.js.map +1 -0
- package/dist/cjs/metric/Levenshtein.js +94 -0
- package/dist/cjs/metric/Levenshtein.js.map +1 -0
- package/dist/cjs/metric/Metric.js +445 -0
- package/dist/cjs/metric/Metric.js.map +1 -0
- package/dist/cjs/metric/NeedlemanWunsch.js +95 -0
- package/dist/cjs/metric/NeedlemanWunsch.js.map +1 -0
- package/dist/cjs/metric/SmithWaterman.js +98 -0
- package/dist/cjs/metric/SmithWaterman.js.map +1 -0
- package/dist/cjs/metric/qGram.js +91 -0
- package/dist/cjs/metric/qGram.js.map +1 -0
- package/dist/cjs/phonetic/Cologne.js +112 -0
- package/dist/cjs/phonetic/Cologne.js.map +1 -0
- package/dist/cjs/phonetic/Metaphone.js +172 -0
- package/dist/cjs/phonetic/Metaphone.js.map +1 -0
- package/dist/cjs/phonetic/Phonetic.js +413 -0
- package/dist/cjs/phonetic/Phonetic.js.map +1 -0
- package/dist/cjs/phonetic/Soundex.js +135 -0
- package/dist/cjs/phonetic/Soundex.js.map +1 -0
- package/dist/cjs/utils/DeepMerge.js +144 -0
- package/dist/cjs/utils/DeepMerge.js.map +1 -0
- package/dist/cjs/utils/DiffChecker.js +500 -0
- package/dist/cjs/utils/DiffChecker.js.map +1 -0
- package/dist/cjs/utils/Filter.js +189 -0
- package/dist/cjs/utils/Filter.js.map +1 -0
- package/dist/cjs/utils/HashTable.js +175 -0
- package/dist/cjs/utils/HashTable.js.map +1 -0
- package/dist/cjs/utils/Normalizer.js +144 -0
- package/dist/cjs/utils/Normalizer.js.map +1 -0
- package/dist/cjs/utils/Pool.js +196 -0
- package/dist/cjs/utils/Pool.js.map +1 -0
- package/dist/cjs/utils/Profiler.js +229 -0
- package/dist/cjs/utils/Profiler.js.map +1 -0
- package/dist/cjs/utils/Registry.js +148 -0
- package/dist/cjs/utils/Registry.js.map +1 -0
- package/dist/cjs/utils/TextAnalyzer.js +358 -0
- package/dist/cjs/utils/TextAnalyzer.js.map +1 -0
- package/dist/esm/CmpStr.js +662 -0
- package/dist/esm/CmpStr.js.map +1 -0
- package/dist/esm/CmpStrAsync.js +331 -0
- package/dist/esm/CmpStrAsync.js.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/metric/Cosine.js +99 -0
- package/dist/esm/metric/Cosine.js.map +1 -0
- package/dist/esm/metric/DamerauLevenshtein.js +108 -0
- package/dist/esm/metric/DamerauLevenshtein.js.map +1 -0
- package/dist/esm/metric/DiceSorensen.js +89 -0
- package/dist/esm/metric/DiceSorensen.js.map +1 -0
- package/dist/esm/metric/Hamming.js +77 -0
- package/dist/esm/metric/Hamming.js.map +1 -0
- package/dist/esm/metric/Jaccard.js +74 -0
- package/dist/esm/metric/Jaccard.js.map +1 -0
- package/dist/esm/metric/JaroWinkler.js +112 -0
- package/dist/esm/metric/JaroWinkler.js.map +1 -0
- package/dist/esm/metric/LCS.js +87 -0
- package/dist/esm/metric/LCS.js.map +1 -0
- package/dist/esm/metric/Levenshtein.js +92 -0
- package/dist/esm/metric/Levenshtein.js.map +1 -0
- package/dist/esm/metric/Metric.js +442 -0
- package/dist/esm/metric/Metric.js.map +1 -0
- package/dist/esm/metric/NeedlemanWunsch.js +93 -0
- package/dist/esm/metric/NeedlemanWunsch.js.map +1 -0
- package/dist/esm/metric/SmithWaterman.js +96 -0
- package/dist/esm/metric/SmithWaterman.js.map +1 -0
- package/dist/esm/metric/qGram.js +89 -0
- package/dist/esm/metric/qGram.js.map +1 -0
- package/dist/esm/phonetic/Cologne.js +114 -0
- package/dist/esm/phonetic/Cologne.js.map +1 -0
- package/dist/esm/phonetic/Metaphone.js +174 -0
- package/dist/esm/phonetic/Metaphone.js.map +1 -0
- package/dist/esm/phonetic/Phonetic.js +409 -0
- package/dist/esm/phonetic/Phonetic.js.map +1 -0
- package/dist/esm/phonetic/Soundex.js +137 -0
- package/dist/esm/phonetic/Soundex.js.map +1 -0
- package/dist/esm/utils/DeepMerge.js +139 -0
- package/dist/esm/utils/DeepMerge.js.map +1 -0
- package/dist/esm/utils/DiffChecker.js +498 -0
- package/dist/esm/utils/DiffChecker.js.map +1 -0
- package/dist/esm/utils/Filter.js +187 -0
- package/dist/esm/utils/Filter.js.map +1 -0
- package/dist/esm/utils/HashTable.js +173 -0
- package/dist/esm/utils/HashTable.js.map +1 -0
- package/dist/esm/utils/Normalizer.js +142 -0
- package/dist/esm/utils/Normalizer.js.map +1 -0
- package/dist/esm/utils/Pool.js +194 -0
- package/dist/esm/utils/Pool.js.map +1 -0
- package/dist/esm/utils/Profiler.js +227 -0
- package/dist/esm/utils/Profiler.js.map +1 -0
- package/dist/esm/utils/Registry.js +142 -0
- package/dist/esm/utils/Registry.js.map +1 -0
- package/dist/esm/utils/TextAnalyzer.js +356 -0
- package/dist/esm/utils/TextAnalyzer.js.map +1 -0
- package/dist/types/CmpStr.d.ts +472 -0
- package/dist/types/CmpStrAsync.d.ts +233 -0
- package/dist/types/index.d.ts +51 -0
- package/dist/types/metric/Cosine.d.ts +57 -0
- package/dist/types/metric/DamerauLevenshtein.d.ts +50 -0
- package/dist/types/metric/DiceSorensen.d.ts +57 -0
- package/dist/types/metric/Hamming.d.ts +49 -0
- package/dist/types/metric/Jaccard.d.ts +48 -0
- package/dist/types/metric/JaroWinkler.d.ts +50 -0
- package/dist/types/metric/LCS.d.ts +50 -0
- package/dist/types/metric/Levenshtein.d.ts +50 -0
- package/dist/types/metric/Metric.d.ts +261 -0
- package/dist/types/metric/NeedlemanWunsch.d.ts +47 -0
- package/dist/types/metric/SmithWaterman.d.ts +48 -0
- package/dist/types/metric/index.d.ts +41 -0
- package/dist/types/metric/qGram.d.ts +56 -0
- package/dist/types/phonetic/Cologne.d.ts +46 -0
- package/dist/types/phonetic/Metaphone.d.ts +50 -0
- package/dist/types/phonetic/Phonetic.d.ts +189 -0
- package/dist/types/phonetic/Soundex.d.ts +49 -0
- package/dist/types/phonetic/index.d.ts +30 -0
- package/dist/types/utils/DeepMerge.d.ts +70 -0
- package/dist/types/utils/DiffChecker.d.ts +137 -0
- package/dist/types/utils/Filter.d.ts +97 -0
- package/dist/types/utils/HashTable.d.ts +86 -0
- package/dist/types/utils/Normalizer.d.ts +76 -0
- package/dist/types/utils/Pool.d.ts +63 -0
- package/dist/types/utils/Profiler.d.ts +129 -0
- package/dist/types/utils/Registry.d.ts +57 -0
- package/dist/types/utils/TextAnalyzer.d.ts +199 -0
- package/dist/types/utils/Types.d.ts +313 -0
- package/package.json +62 -49
- package/src/CmpStr.d.ts +0 -70
- package/src/CmpStr.js +0 -912
- package/src/CmpStrAsync.d.ts +0 -19
- package/src/CmpStrAsync.js +0 -204
- package/src/algorithms/cosine.js +0 -86
- package/src/algorithms/damerau.js +0 -78
- package/src/algorithms/dice.js +0 -65
- package/src/algorithms/hamming.js +0 -44
- package/src/algorithms/jaccard.js +0 -34
- package/src/algorithms/jaroWinkler.js +0 -106
- package/src/algorithms/lcs.js +0 -58
- package/src/algorithms/levenshtein.js +0 -70
- package/src/algorithms/needlemanWunsch.js +0 -72
- package/src/algorithms/qGram.js +0 -63
- package/src/algorithms/smithWaterman.js +0 -78
- package/src/algorithms/soundex.js +0 -152
- package/src/index.d.ts +0 -3
- package/src/index.js +0 -47
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
// CmpStr v3.0.0 dev-1a82e20-250612 by Paul Köhler @komed3 / MIT License
|
|
2
|
+
import { Registry } from '../utils/Registry.js';
|
|
3
|
+
import { HashTable } from '../utils/HashTable.js';
|
|
4
|
+
import { Profiler } from '../utils/Profiler.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Abstract Metric
|
|
8
|
+
* src/metric/Metric.ts
|
|
9
|
+
*
|
|
10
|
+
* This module defines an abstract class for string metrics, providing a framework for
|
|
11
|
+
* computing various string similarity metrics. It includes methods for running metrics
|
|
12
|
+
* in different modes (single, batch, pairwise) synchronous or asynchronous and caching
|
|
13
|
+
* results to optimize performance. The class is designed to be extended by specific
|
|
14
|
+
* metric implementations like the Levenshtein distance or Jaro-Winkler similarity.
|
|
15
|
+
*
|
|
16
|
+
* It provides:
|
|
17
|
+
* - A base class for string metrics with common functionality
|
|
18
|
+
* - Methods for running metrics in different modes
|
|
19
|
+
* - Pre-computation for trivial cases to optimize performance
|
|
20
|
+
* - Caching of metric computations to avoid redundant calculations
|
|
21
|
+
* - Support for symmetrical metrics (same result for inputs in any order)
|
|
22
|
+
* - Performance tracking capabilities (Profiler)
|
|
23
|
+
* - Asynchronous execution support for metrics
|
|
24
|
+
*
|
|
25
|
+
* This class is intended to be extended by specific metric implementations that will
|
|
26
|
+
* implement the `compute` method to define the specific metric computation logic.
|
|
27
|
+
*
|
|
28
|
+
* @module Metric
|
|
29
|
+
* @author Paul Köhler (komed3)
|
|
30
|
+
* @license MIT
|
|
31
|
+
*/
|
|
32
|
+
// Get the singleton profiler instance for performance monitoring
|
|
33
|
+
const profiler = Profiler.getInstance();
|
|
34
|
+
/**
|
|
35
|
+
* Abstract class representing a generic string metric.
|
|
36
|
+
*
|
|
37
|
+
* @abstract
|
|
38
|
+
* @template R - The type of the raw result, defaulting to `MetricRaw`.
|
|
39
|
+
*/
|
|
40
|
+
class Metric {
|
|
41
|
+
// Cache for metric computations to avoid redundant calculations
|
|
42
|
+
static cache = new HashTable();
|
|
43
|
+
// Metric name for identification
|
|
44
|
+
metric;
|
|
45
|
+
// Inputs for the metric computation, transformed into arrays
|
|
46
|
+
a;
|
|
47
|
+
b;
|
|
48
|
+
// Store original inputs for result mapping
|
|
49
|
+
origA = [];
|
|
50
|
+
origB = [];
|
|
51
|
+
// Options for the metric computation, such as performance tracking
|
|
52
|
+
options;
|
|
53
|
+
// Indicates whether the metric is symmetric (same result for inputs in any order)
|
|
54
|
+
symmetric;
|
|
55
|
+
/**
|
|
56
|
+
* Result of the metric computation, which can be a single result or an array of results.
|
|
57
|
+
* This will be populated after running the metric.
|
|
58
|
+
*/
|
|
59
|
+
results;
|
|
60
|
+
/**
|
|
61
|
+
* Static method to clear the cache of metric computations.
|
|
62
|
+
*/
|
|
63
|
+
static clear() {
|
|
64
|
+
this.cache.clear();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Swaps two strings and their lengths if the first is longer than the second.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} a - First string
|
|
70
|
+
* @param {string} b - Second string
|
|
71
|
+
* @param {number} m - Length of the first string
|
|
72
|
+
* @param {number} n - Length of the second string
|
|
73
|
+
* @returns {[string, string, number, number]} - Swapped strings and lengths
|
|
74
|
+
*/
|
|
75
|
+
static swap(a, b, m, n) {
|
|
76
|
+
return m > n ? [b, a, n, m] : [a, b, m, n];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Clamps the similarity result between 0 and 1.
|
|
80
|
+
*
|
|
81
|
+
* @param {number} res - The input similarity to clamp
|
|
82
|
+
* @returns {number} - The clamped similarity (0 to 1)
|
|
83
|
+
*/
|
|
84
|
+
static clamp(res) {
|
|
85
|
+
return Math.max(0, Math.min(1, res));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Constructor for the Metric class.
|
|
89
|
+
* Initializes the metric with two inputs (strings or arrays of strings) and options.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} metric - The name of the metric (e.g. 'levenshtein')
|
|
92
|
+
* @param {MetricInput} a - First input string or array of strings
|
|
93
|
+
* @param {MetricInput} b - Second input string or array of strings
|
|
94
|
+
* @param {MetricOptions} [opt] - Options for the metric computation
|
|
95
|
+
* @param {boolean} [symmetric=false] - Whether the metric is symmetric (same result for inputs in any order)
|
|
96
|
+
* @throws {Error} - If inputs `a` or `b` are empty
|
|
97
|
+
*/
|
|
98
|
+
constructor(metric, a, b, opt = {}, symmetric = false) {
|
|
99
|
+
// Set the metric name
|
|
100
|
+
this.metric = metric;
|
|
101
|
+
// Set the inputs
|
|
102
|
+
this.a = Array.isArray(a) ? a : [a];
|
|
103
|
+
this.b = Array.isArray(b) ? b : [b];
|
|
104
|
+
// Validate inputs: ensure they are not empty
|
|
105
|
+
if (this.a.length === 0 || this.b.length === 0)
|
|
106
|
+
throw new Error(`inputs <a> and <b> must not be empty`);
|
|
107
|
+
// Set options
|
|
108
|
+
this.options = opt;
|
|
109
|
+
this.symmetric = symmetric;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Pre-compute the metric for two strings.
|
|
113
|
+
* This method is called before the actual computation to handle trivial cases.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} a - First string
|
|
116
|
+
* @param {string} b - Second string
|
|
117
|
+
* @param {number} m - Length of the first string
|
|
118
|
+
* @param {number} n - Length of the second string
|
|
119
|
+
* @returns {MetricCompute<R>|undefined} - Pre-computed result or undefined if not applicable
|
|
120
|
+
*/
|
|
121
|
+
preCompute(a, b, m, n) {
|
|
122
|
+
// If strings are identical, return a similarity of 1
|
|
123
|
+
if (a === b) return { res: 1 };
|
|
124
|
+
// If the lengths of both strings is less than 2, return a similarity of 0
|
|
125
|
+
if (m == 0 || n == 0 || (m < 2 && n < 2)) return { res: 0 };
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Abstract method to be implemented by subclasses to perform the metric computation.
|
|
130
|
+
* This method should contain the logic for computing the metric between two strings.
|
|
131
|
+
*
|
|
132
|
+
* @param {string} a - First string
|
|
133
|
+
* @param {string} b - Second string
|
|
134
|
+
* @param {number} m - Length of the first string
|
|
135
|
+
* @param {number} n - Length of the second string
|
|
136
|
+
* @param {number} maxLen - Maximum length of the strings
|
|
137
|
+
* @returns {MetricCompute<R>} - The result of the metric computation
|
|
138
|
+
* @throws {Error} - If not overridden in a subclass
|
|
139
|
+
*/
|
|
140
|
+
compute(a, b, m, n, maxLen) {
|
|
141
|
+
throw new Error(`method compute() must be overridden in a subclass`);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Run the metric computation for single inputs (two strings).
|
|
145
|
+
* Applies preCompute for trivial cases before cache lookup and computation.
|
|
146
|
+
*
|
|
147
|
+
* If the profiler is active, it will measure time and memory usage.
|
|
148
|
+
*
|
|
149
|
+
* @param {number} i - Pointer to the first string
|
|
150
|
+
* @param {number} j - Pointer to the second string
|
|
151
|
+
* @returns {MetricResultSingle<R>} - The result of the metric computation
|
|
152
|
+
*/
|
|
153
|
+
runSingle(i, j) {
|
|
154
|
+
// Type safety: convert inputs to strings
|
|
155
|
+
let a = String(this.a[i]),
|
|
156
|
+
A = a;
|
|
157
|
+
let b = String(this.b[j]),
|
|
158
|
+
B = b;
|
|
159
|
+
// Get lengths
|
|
160
|
+
let m = A.length,
|
|
161
|
+
n = B.length;
|
|
162
|
+
// Pre-compute trivial cases (identical, empty, etc.)
|
|
163
|
+
let result = this.preCompute(A, B, m, n);
|
|
164
|
+
if (!result) {
|
|
165
|
+
// If the profiler is enabled, measure; else, just run
|
|
166
|
+
result = profiler.run(() => {
|
|
167
|
+
// Generate a cache key based on the metric and pair of strings `a` and `b`
|
|
168
|
+
const key = Metric.cache.key(this.metric, [A, B], this.symmetric);
|
|
169
|
+
// If the key exists in the cache, return the cached result
|
|
170
|
+
// Otherwise, compute the metric using the algorithm
|
|
171
|
+
return (
|
|
172
|
+
Metric.cache.get(key || '') ??
|
|
173
|
+
(() => {
|
|
174
|
+
// If the metric is symmetrical, swap `a` and `b` (shorter string first)
|
|
175
|
+
if (this.symmetric) [A, B, m, n] = Metric.swap(A, B, m, n);
|
|
176
|
+
// Compute the similarity using the algorithm
|
|
177
|
+
const res = this.compute(A, B, m, n, Math.max(m, n));
|
|
178
|
+
// If a key was generated, store the result in the cache
|
|
179
|
+
if (key) Metric.cache.set(key, res);
|
|
180
|
+
return res;
|
|
181
|
+
})()
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// Build metric result object
|
|
186
|
+
return {
|
|
187
|
+
metric: this.metric,
|
|
188
|
+
a: this.origA[i] ?? a,
|
|
189
|
+
b: this.origB[j] ?? b,
|
|
190
|
+
...result
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Run the metric computation for single inputs (two strings) asynchronously.
|
|
195
|
+
*
|
|
196
|
+
* @param {number} i - Pointer to the first string
|
|
197
|
+
* @param {number} j - Pointer to the second string
|
|
198
|
+
* @returns {Promise<MetricResultSingle<R>>} - Promise resolving the result of the metric computation
|
|
199
|
+
*/
|
|
200
|
+
async runSingleAsync(i, j) {
|
|
201
|
+
return Promise.resolve(this.runSingle(i, j));
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Run the metric computation for batch inputs (arrays of strings).
|
|
205
|
+
*
|
|
206
|
+
* It iterates through each string in the first array and computes the metric
|
|
207
|
+
* against each string in the second array.
|
|
208
|
+
*/
|
|
209
|
+
runBatch() {
|
|
210
|
+
const results = [];
|
|
211
|
+
// Loop through each combination of strings in a[] and b[]
|
|
212
|
+
for (let i = 0; i < this.a.length; i++)
|
|
213
|
+
for (let j = 0; j < this.b.length; j++)
|
|
214
|
+
results.push(this.runSingle(i, j));
|
|
215
|
+
// Populate the results
|
|
216
|
+
// `this.results` will be an array of MetricResultSingle
|
|
217
|
+
this.results = results;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Run the metric computation for batch inputs (arrays of strings) asynchronously.
|
|
221
|
+
*/
|
|
222
|
+
async runBatchAsync() {
|
|
223
|
+
const results = [];
|
|
224
|
+
// Loop through each combination of strings in a[] and b[]
|
|
225
|
+
for (let i = 0; i < this.a.length; i++)
|
|
226
|
+
for (let j = 0; j < this.b.length; j++)
|
|
227
|
+
results.push(await this.runSingleAsync(i, j));
|
|
228
|
+
// Populate the results
|
|
229
|
+
// `this.results` will be an array of MetricResultSingle
|
|
230
|
+
this.results = results;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Run the metric computation for pairwise inputs (A[i] vs B[i]).
|
|
234
|
+
*
|
|
235
|
+
* This method assumes that both `a` and `b` are arrays of equal length
|
|
236
|
+
* and computes the metric only for corresponding index pairs.
|
|
237
|
+
*/
|
|
238
|
+
runPairwise() {
|
|
239
|
+
const results = [];
|
|
240
|
+
// Compute metric for each corresponding pair
|
|
241
|
+
for (let i = 0; i < this.a.length; i++) results.push(this.runSingle(i, i));
|
|
242
|
+
// Populate the results
|
|
243
|
+
// `this.results` will be an array of MetricResultSingle
|
|
244
|
+
this.results = results;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Run the metric computation for pairwise inputs (A[i] vs B[i]) asynchronously.
|
|
248
|
+
*/
|
|
249
|
+
async runPairwiseAsync() {
|
|
250
|
+
const results = [];
|
|
251
|
+
// Compute metric for each corresponding pair
|
|
252
|
+
for (let i = 0; i < this.a.length; i++)
|
|
253
|
+
results.push(await this.runSingleAsync(i, i));
|
|
254
|
+
// Populate the results
|
|
255
|
+
// `this.results` will be an array of MetricResultSingle
|
|
256
|
+
this.results = results;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Set the original inputs to which the results of the metric calculation will refer.
|
|
260
|
+
*
|
|
261
|
+
* @param {MetricInput} [a] - original input(s) for a
|
|
262
|
+
* @param {MetricInput} [b] - original input(s) for b
|
|
263
|
+
*/
|
|
264
|
+
setOriginal(a, b) {
|
|
265
|
+
if (a) this.origA = Array.isArray(a) ? a : [a];
|
|
266
|
+
if (b) this.origB = Array.isArray(b) ? b : [b];
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Check if the inputs are in batch mode.
|
|
271
|
+
*
|
|
272
|
+
* This method checks if either `a` or `b` contains more than one string,
|
|
273
|
+
* indicating that the metric is being run in batch mode.
|
|
274
|
+
*
|
|
275
|
+
* @returns {boolean} - True if either input is an array with more than one element
|
|
276
|
+
*/
|
|
277
|
+
isBatch() {
|
|
278
|
+
return this.a.length > 1 || this.b.length > 1;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Check if the inputs are in single mode.
|
|
282
|
+
*
|
|
283
|
+
* This method checks if both `a` and `b` are single strings (not arrays),
|
|
284
|
+
* indicating that the metric is being run on a single pair of strings.
|
|
285
|
+
*
|
|
286
|
+
* @returns {boolean} - True if both inputs are single strings
|
|
287
|
+
*/
|
|
288
|
+
isSingle() {
|
|
289
|
+
return !this.isBatch();
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Check if the inputs are in pairwise mode.
|
|
293
|
+
*
|
|
294
|
+
* This method checks if both `a` and `b` are arrays of the same length,
|
|
295
|
+
* indicating that the metric is being run on corresponding pairs of strings.
|
|
296
|
+
*
|
|
297
|
+
* @returns {boolean} - True if both inputs are arrays of equal length
|
|
298
|
+
* @param {boolean} [safe=false] - If true, does not throw an error if lengths are not equal
|
|
299
|
+
* @throws {Error} - If `safe` is false and the lengths of `a` and `b` are not equal
|
|
300
|
+
*/
|
|
301
|
+
isPairwise(safe = false) {
|
|
302
|
+
return this.isBatch() && this.a.length === this.b.length
|
|
303
|
+
? true
|
|
304
|
+
: !safe &&
|
|
305
|
+
(() => {
|
|
306
|
+
throw new Error(`mode <pairwise> requires arrays of equal length`);
|
|
307
|
+
})();
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Check if the metric is symmetrical.
|
|
311
|
+
*
|
|
312
|
+
* This method returns whether the metric is symmetric, meaning it produces the same
|
|
313
|
+
* result regardless of the order of inputs (e.g., Levenshtein distance).
|
|
314
|
+
*
|
|
315
|
+
* @returns {boolean} - True if the metric is symmetric
|
|
316
|
+
*/
|
|
317
|
+
isSymmetrical() {
|
|
318
|
+
return this.symmetric;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Determine which mode to run the metric in.
|
|
322
|
+
*
|
|
323
|
+
* This method checks the provided mode or defaults to the mode specified in options.
|
|
324
|
+
* If no mode is specified, it defaults to 'default'.
|
|
325
|
+
*
|
|
326
|
+
* @param {MetricMode} [mode] - The mode to run the metric in (optional)
|
|
327
|
+
* @returns {MetricMode} - The determined mode
|
|
328
|
+
*/
|
|
329
|
+
whichMode(mode) {
|
|
330
|
+
return mode ?? this.options?.mode ?? 'default';
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Clear the cached results of the metric.
|
|
334
|
+
*
|
|
335
|
+
* This method resets the `results` property to `undefined`, effectively clearing
|
|
336
|
+
* any previously computed results. It can be useful for re-running the metric
|
|
337
|
+
* with new inputs or options.
|
|
338
|
+
*/
|
|
339
|
+
clear() {
|
|
340
|
+
this.results = undefined;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Run the metric computation based on the specified mode.
|
|
344
|
+
*
|
|
345
|
+
* @param {MetricMode} [mode] - The mode to run the metric in (optional)
|
|
346
|
+
* @param {boolean} [clear=true] - Whether to clear previous results before running
|
|
347
|
+
* @throws {Error} - If an unsupported mode is specified
|
|
348
|
+
*/
|
|
349
|
+
run(mode, clear = true) {
|
|
350
|
+
// Clear previous results if requested
|
|
351
|
+
if (clear) this.clear();
|
|
352
|
+
switch (this.whichMode(mode)) {
|
|
353
|
+
// Default mode runs the metric on single inputs or falls back to batch mode
|
|
354
|
+
case 'default':
|
|
355
|
+
if (this.isSingle()) {
|
|
356
|
+
this.results = this.runSingle(0, 0);
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
// Batch mode runs the metric on all combinations of a[] and b[]
|
|
360
|
+
case 'batch':
|
|
361
|
+
this.runBatch();
|
|
362
|
+
break;
|
|
363
|
+
// Single mode runs the metric on the first elements of a[] and b[]
|
|
364
|
+
case 'single':
|
|
365
|
+
this.results = this.runSingle(0, 0);
|
|
366
|
+
break;
|
|
367
|
+
// Pairwise mode runs the metric on corresponding pairs of a[] and b[]
|
|
368
|
+
case 'pairwise':
|
|
369
|
+
if (this.isPairwise()) this.runPairwise();
|
|
370
|
+
break;
|
|
371
|
+
// Unsupported mode
|
|
372
|
+
default:
|
|
373
|
+
throw new Error(`unsupported mode <${mode}>`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Run the metric computation based on the specified mode asynchronously.
|
|
378
|
+
*
|
|
379
|
+
* @param {MetricMode} [mode] - The mode to run the metric in (optional)
|
|
380
|
+
* @param {boolean} [clear=true] - Whether to clear previous results before running
|
|
381
|
+
* @returns {Promise<void>} - A promise that resolves when the metric computation is complete
|
|
382
|
+
* @throws {Error} - If an unsupported mode is specified
|
|
383
|
+
*/
|
|
384
|
+
async runAsync(mode, clear = true) {
|
|
385
|
+
// Clear previous results if requested
|
|
386
|
+
if (clear) this.clear();
|
|
387
|
+
switch (this.whichMode(mode)) {
|
|
388
|
+
// Default mode runs the metric on single inputs or falls back to batch mode
|
|
389
|
+
case 'default':
|
|
390
|
+
if (this.isSingle()) {
|
|
391
|
+
this.results = await this.runSingleAsync(0, 0);
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
// Batch mode runs the metric on all combinations of a[] and b[]
|
|
395
|
+
case 'batch':
|
|
396
|
+
await this.runBatchAsync();
|
|
397
|
+
break;
|
|
398
|
+
// Single mode runs the metric on the first elements of a[] and b[]
|
|
399
|
+
case 'single':
|
|
400
|
+
this.results = await this.runSingleAsync(0, 0);
|
|
401
|
+
break;
|
|
402
|
+
// Pairwise mode runs the metric on corresponding pairs of a[] and b[]
|
|
403
|
+
case 'pairwise':
|
|
404
|
+
if (this.isPairwise()) await this.runPairwiseAsync();
|
|
405
|
+
break;
|
|
406
|
+
// Unsupported mode
|
|
407
|
+
default:
|
|
408
|
+
throw new Error(`unsupported async mode <${mode}>`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Get the name of the metric.
|
|
413
|
+
*
|
|
414
|
+
* @returns {string} - The name of the metric
|
|
415
|
+
*/
|
|
416
|
+
getMetricName() {
|
|
417
|
+
return this.metric;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Get the result of the metric computation.
|
|
421
|
+
*
|
|
422
|
+
* @returns {MetricResult<R>} - The result of the metric computation
|
|
423
|
+
* @throws {Error} - If `run()` has not been called before this method
|
|
424
|
+
*/
|
|
425
|
+
getResults() {
|
|
426
|
+
// Ensure that the metric has been run before getting the result
|
|
427
|
+
if (this.results === undefined)
|
|
428
|
+
throw new Error(`run() must be called before getResult()`);
|
|
429
|
+
// Return the result(s)
|
|
430
|
+
return this.results;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Metric registry service for managing metric implementations.
|
|
435
|
+
*
|
|
436
|
+
* This registry allows for dynamic registration and retrieval of metric classes,
|
|
437
|
+
* enabling the use of various string similarity metrics in a consistent manner.
|
|
438
|
+
*/
|
|
439
|
+
const MetricRegistry = Registry('metric', Metric);
|
|
440
|
+
|
|
441
|
+
export { Metric, MetricRegistry };
|
|
442
|
+
//# sourceMappingURL=Metric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Metric.js","sources":["../../../src/metric/Metric.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// CmpStr v3.0.0 dev-1a82e20-250612 by Paul Köhler @komed3 / MIT License
|
|
2
|
+
import { MetricRegistry, Metric } from './Metric.js';
|
|
3
|
+
import { Pool } from '../utils/Pool.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Needleman-Wunsch Algorithm
|
|
7
|
+
* src/metric/NeedlemanWunsch.ts
|
|
8
|
+
*
|
|
9
|
+
* @see https://en.wikipedia.org/wiki/Needleman%E2%80%93Wunsch_algorithm
|
|
10
|
+
*
|
|
11
|
+
* The Needleman-Wunsch algorithm performs global alignment, aligning two strings
|
|
12
|
+
* entirely, including gaps. It is commonly used in bioinformatics for sequence
|
|
13
|
+
* alignment.
|
|
14
|
+
*
|
|
15
|
+
* @module Metric/NeedlemanWunsch
|
|
16
|
+
* @author Paul Köhler (komed3)
|
|
17
|
+
* @license MIT
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* NeedlemanWunschDistance class extends the Metric class to implement the Needleman-Wunsch algorithm.
|
|
21
|
+
*/
|
|
22
|
+
class NeedlemanWunschDistance extends Metric {
|
|
23
|
+
/**
|
|
24
|
+
* Constructor for the NeedlemanWunsch class.
|
|
25
|
+
*
|
|
26
|
+
* Initializes the Needleman-Wunsch metric with two input strings or
|
|
27
|
+
* arrays of strings and optional options.
|
|
28
|
+
*
|
|
29
|
+
* @param {MetricInput} a - First input string or array of strings
|
|
30
|
+
* @param {MetricInput} b - Second input string or array of strings
|
|
31
|
+
* @param {MetricOptions} [opt] - Options for the metric computation
|
|
32
|
+
*/
|
|
33
|
+
constructor(a, b, opt = {}) {
|
|
34
|
+
// Call the parent Metric constructor with the metric name and inputs
|
|
35
|
+
// Metric is symmetrical
|
|
36
|
+
super('needlemanWunsch', a, b, opt, true);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Calculates the Needleman-Wunsch global alignment score between two strings.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} a - First string
|
|
42
|
+
* @param {string} b - Second string
|
|
43
|
+
* @param {number} m - Length of the first string
|
|
44
|
+
* @param {number} n - Length of the second string
|
|
45
|
+
* @param {number} maxLen - Maximum length of the strings
|
|
46
|
+
* @return {MetricCompute<NeedlemanRaw>} - Object containing the similarity result and raw score
|
|
47
|
+
*/
|
|
48
|
+
compute(a, b, m, n, maxLen) {
|
|
49
|
+
// Scoring parameters (can be customized via options if needed)
|
|
50
|
+
const { match = 1, mismatch = -1, gap = -1 } = this.options;
|
|
51
|
+
// Get two reusable arrays from the Pool for the DP rows
|
|
52
|
+
const len = m + 1;
|
|
53
|
+
const [prev, curr] = Pool.acquireMany('uint16', [len, len]);
|
|
54
|
+
// Initialize the first row (gap penalties)
|
|
55
|
+
prev[0] = 0;
|
|
56
|
+
for (let i = 1; i <= m; i++) prev[i] = prev[i - 1] + gap;
|
|
57
|
+
// Fill the DP matrix row by row (over the longer string)
|
|
58
|
+
for (let j = 1; j <= n; j++) {
|
|
59
|
+
curr[0] = prev[0] + gap;
|
|
60
|
+
// Get the character code of the current character in b
|
|
61
|
+
const cb = b.charCodeAt(j - 1);
|
|
62
|
+
for (let i = 1; i <= m; i++) {
|
|
63
|
+
// Score for match / mismatch
|
|
64
|
+
const score = a.charCodeAt(i - 1) === cb ? match : mismatch;
|
|
65
|
+
// Calculate the maximum score for current cell
|
|
66
|
+
curr[i] = Math.max(
|
|
67
|
+
prev[i - 1] + score, // Diagonal (match/mismatch)
|
|
68
|
+
prev[i] + gap, // Up (gap)
|
|
69
|
+
curr[i - 1] + gap // Left (gap)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
// Copy current row to previous for next iteration
|
|
73
|
+
prev.set(curr);
|
|
74
|
+
}
|
|
75
|
+
// The last value in prev is the Needleman-Wunsch score
|
|
76
|
+
const score = prev[m];
|
|
77
|
+
// Release arrays back to the pool
|
|
78
|
+
Pool.release('uint16', prev, len);
|
|
79
|
+
Pool.release('uint16', curr, len);
|
|
80
|
+
// Use the maximum possible score for the longer string (global alignment)
|
|
81
|
+
const denum = maxLen * match;
|
|
82
|
+
// Return the result as a MetricCompute object
|
|
83
|
+
return {
|
|
84
|
+
res: denum === 0 ? 0 : Metric.clamp(score / denum),
|
|
85
|
+
raw: { score, denum }
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Register the Needleman-Wunsch algorithm in the metric registry
|
|
90
|
+
MetricRegistry.add('needlemanWunsch', NeedlemanWunschDistance);
|
|
91
|
+
|
|
92
|
+
export { NeedlemanWunschDistance };
|
|
93
|
+
//# sourceMappingURL=NeedlemanWunsch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NeedlemanWunsch.js","sources":["../../../src/metric/NeedlemanWunsch.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|