min-mphash 0.5.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/README.zh.md ADDED
@@ -0,0 +1,323 @@
1
+ # MinMPHash & MinMPLookup
2
+
3
+ > Mini Minimal Perfect Hash & Mini Minimal Perfect Lookup
4
+
5
+ [English README](./README.en.md)
6
+
7
+ TypeScript/JavaScript 平台上的最小完美哈希与查找工具实现。
8
+
9
+ `MinMPHash` 可以把一组数量为 n 的字符串映射到 `[0, n-1]` 的整数范围内,且不会有冲突。
10
+
11
+ `MinMPLookup` 则是在 `MinMPHash` 的基础上实现的最小完美查找表工具。
12
+
13
+ 它可以把形如 `{ key1: [value1, value2, ...], key2: [value3, value4, ...] }` 的映射表最小化存储,从而实现根据 `value` 查找对应 `key` 的需求。
14
+
15
+ 相比原样存储,最小化的查找表可以将体积缩小到原来的 10% 以下(具体压缩率取决于数据集中 values 的信息熵,熵越大压缩效果越好)。
16
+
17
+ ## 什么是最小完美哈希?
18
+
19
+ 哈希函数可以把数据映射到一个范围内,生成固定长度的“指纹”。但普通哈希函数有两个常见问题:
20
+
21
+ - 稀疏性导致的空间浪费:哈希值域通常远大于实际数据量,哈希表会非常稀疏。
22
+ - 不同输入可能产生冲突:不同的输入可能映射到相同的哈希值,为了降低冲突率通常需要更长的哈希值,从而浪费空间。
23
+
24
+ 最小完美哈希函数(Minimal Perfect Hash Function,MPHF)是一类特殊哈希函数:
25
+
26
+ - 它对给定的 n 个不同输入保证无冲突;
27
+ - 输出范围恰好为 `[0, n-1]`,使得空间利用达到最优。
28
+
29
+ 换句话说,如果你有 n 个不同的字符串,MPHF 会把它们一一映射到 `[0, n-1]` 的整数范围内,每个字符串对应一个唯一索引。
30
+
31
+ ```
32
+ text set Hash Hash Table (Sparse)
33
+ +----------+ +------------+ +-------------------+
34
+ | Apple | ----> | h(x) | ----> | 0: [ Apple ] |
35
+ | Banana | +------------+ | 1: | <--- Gap
36
+ | Cherry | | 2: [ Banana ] |
37
+ +----------+ | 3: | <--- Gap
38
+ | ... | <--- Gap
39
+ | 9: [ Cherry ] |
40
+ +-------------------+
41
+ (Waste of Space)
42
+
43
+
44
+ text set 🤩 Minimal Perfect Hash Hash Table (Compact)
45
+ +----------+ +--------------+ +-------------------+
46
+ | Apple | ----> | mmph(x) | ----> | 0: [ Apple ] |
47
+ | Banana | +--------------+ | 1: [ Banana ] |
48
+ | Cherry | | 2: [ Cherry ] |
49
+ +----------+ +-------------------+
50
+ ( 100% Space Utilization )
51
+
52
+ ```
53
+
54
+ ## 什么时候使用最小完美哈希?
55
+
56
+ 最小完美哈希适用于需要将一组确定性的键(Key)映射为紧凑整数索引的场景。与普通映射表相比,使用 MPHF 可以省去存储完整键的开销:只需存储键对应的整数索引即可实现相同的映射功能。
57
+
58
+ 换言之,只要键在数据集中是确定的(不会变化),无论键本身有多长,都可以用一个基于数据集大小的 `number` 存储并唯一标识该键,而不会产生冲突。
59
+
60
+ 这正是常见哈希(如 MD5、SHA-1)做不到的:它们产生的哈希值较长(如 MD5 为 16 字节、SHA-1 为 20 字节),而 MPHF 能根据数据集大小选择最小的整数范围,从而达到更高的空间利用率。
61
+
62
+ 举一个例子,有一组字体名称列表,要从根据字体名映射到字体的系列名
63
+ 一般的方法是通过一个映射表来完成这一切:
64
+
65
+ ```js
66
+ let FontMap = {
67
+ "Source Sans": "Source Sans",
68
+ "Source Sans Black": "Source Sans",
69
+ "Source Sans Bold": "Source Sans",
70
+ "思源黑体 CN ExtraLight": "Source Sans",
71
+ "思源黑体 TW Light": "Source Sans",
72
+ // ... 6000+
73
+ };
74
+
75
+ let query = "思源黑体 TW Light";
76
+ let found = FontMap[query]; // 'Source Sans'
77
+ ```
78
+
79
+ 这样的映射表需要存储所有的键(如字体名称),当键数量较多时会非常占空间。使用最小完美哈希后,我们可以只存储字体名称对应的索引(哈希值),而不是完整名称:
80
+
81
+ ```js
82
+ // 创建包含所有字体名称的集合
83
+ let values = [
84
+ "Source Sans",
85
+ "Source Sans Black",
86
+ "Source Sans Bold",
87
+ "思源黑体 CN ExtraLight",
88
+ "思源黑体 TW Light",
89
+ // ... 6000+
90
+ ];
91
+
92
+ // 根据 values 创建最小完美哈希字典
93
+ let dict = createMinMPHashDict(values);
94
+ // 根据字典创建哈希函数实例
95
+ let minHash = new MinMPHash(dict);
96
+
97
+ // 然后我们使用哈希值来代替完整的字体名称:
98
+ let FontMapWithHash = {
99
+ "Source Sans": [1, 2, 3, 21 /* ... */],
100
+ Heiti: [12, 12 /* ... */],
101
+ "JetBrains Mono": [32, 112 /* ... */],
102
+ // ...
103
+ };
104
+
105
+ // 查询时,先计算哈希值,再通过哈希值查找对应的字体系列名
106
+ let query = "思源黑体 TW Light";
107
+ let query_hash = minHash.hash(query, dict); // e.g. 42
108
+
109
+ let found = Object.entries(FontMapWithHash).find(([family, hashes]) =>
110
+ hashes.includes(query_hash)
111
+ )[0]; // 'Source Sans'
112
+ ```
113
+
114
+ 这样可以显著减少存储空间,因为不再需要保存完整的键文本,只需保存更短的整数索引。
115
+
116
+ 你可能会想到 MD5 或 SHA-1 之类的哈希函数也能生成标识,但它们的哈希值较长(如 MD5 为 16 字节、SHA-1 为 20 字节)。FNV-1a 在某些场景下可用到最少 4 字节,但其冲突率较高。最小完美哈希可根据数据集大小选择最小范围,保证无冲突并实现极致的空间利用。
117
+
118
+ ## 使用方法
119
+
120
+ ### 安装
121
+
122
+ ```bash
123
+ npm install min-mphash
124
+ ```
125
+
126
+ ### MinMPHash 最小完美哈希的使用
127
+
128
+ 这是最核心的功能,用于将一组字符串映射到 `[0, n-1]` 的整数。
129
+
130
+ #### 步骤 1: 创建字典 (构建时)
131
+
132
+ 在你的构建脚本或服务端代码中,生成哈希字典。
133
+
134
+ ```typescript
135
+ import { createMinMPHashDict } from "min-mphash";
136
+ import * as fs from "fs";
137
+
138
+ // 示例字符串集合
139
+ const mySet = ["Apple", "Banana", "Cherry", "Date", "Elderberry"];
140
+
141
+ // 创建字典二进制数据
142
+ // outputBinary: true 返回 Uint8Array,适合存储或网络传输
143
+ const dictBuffer = createMinMPHashDict(mySet, {
144
+ outputBinary: true,
145
+ level: 5, // 优化级别 [1-10],越高体积越小但构建越慢
146
+ });
147
+
148
+ fs.writeFileSync("mph-dict.bin", dictBuffer);
149
+ ```
150
+
151
+ #### 步骤 2: 使用字典生成哈希值 (运行时)
152
+
153
+ 在你的应用(如浏览器端)加载字典并进行哈希查询。
154
+
155
+ ```typescript
156
+ import { MinMPHash } from "min-mphash";
157
+
158
+ // 假设你已经加载了二进制数据
159
+ const dictBuffer = await fetch("mph-dict.bin").then((res) => res.arrayBuffer());
160
+ const dict = new Uint8Array(dictBuffer);
161
+
162
+ const mph = new MinMPHash(dict);
163
+
164
+ console.log(mph.hash("Apple")); // 0 (或其他 0-4 之间的唯一值)
165
+ console.log(mph.hash("Banana")); // 2
166
+ console.log(mph.hash("Cherry")); // 4
167
+
168
+ // 注意:对于不在集合中的字符串,它也会返回一个 [0, n-1] 的值(这是 MPHF 的特性),
169
+ // 除非你启用了**校验模式**(见下文)。
170
+ console.log(mph.hash("sdfsd94jx#*")); // 可能返回 1
171
+ ```
172
+
173
+ #### 校验模式 `onlySet`
174
+
175
+ 标准的最小完美哈希函数对于**不在集合中**的输入也会返回一个 `[0, n-1]` 范围内的索引(这属于 MPHF 的性质)。如果你的应用需要把集合外的查询识别为“未命中”,可以在创建字典时启用校验模式 `onlySet`。
176
+
177
+ `onlySet` 会以额外空间为代价存储每个键的指纹(fingerprint),查询时会校验指纹:若校验失败则返回 `-1` 表示未命中。
178
+
179
+ ```typescript
180
+ let dict = createMinMPHashDict(mySet, { onlySet: "8" });
181
+ ```
182
+
183
+ | onlySet | 空间占用(每 key) | 误判率 |
184
+ | ------- | ------------------ | ------------ |
185
+ | 2 | 0.25 byte | ~25% |
186
+ | 4 | 0.5 byte | ~6.25% |
187
+ | 8 | 1 byte | ~0.39% |
188
+ | 16 | 2 bytes | ~0.0015% |
189
+ | 32 | 4 bytes | ~0.00000002% |
190
+
191
+ 注:表中“误判率”指的是对于不在集合中的输入,被错误判定为在集合中的概率;如果键确实在集合中,校验总是成功。
192
+
193
+ #### 字典格式:JSON/CBOR/CBOR.Gzip
194
+
195
+ `createMinMPHashDict` 可以输出多种格式的字典:
196
+
197
+ - **二进制**
198
+ `{ outputBinary: true }`
199
+ 返回 CBOR `Uint8Array`
200
+ - **压缩二进制**
201
+ `{ outputBinary: true, enableCompression: true}`
202
+ Gzip 压缩后的 CBOR `Uint8Array`
203
+ - **JSON**
204
+ `默认`
205
+ JavaScript 对象,适合调试和查看。
206
+
207
+ 通常来说,推荐使用压缩二进制格式,体积最小,
208
+ 但 JSON 开发时比较方便,如果服务器/CDN 支持透明压缩,
209
+ 可以直接使用 JSON 格式,最终体积相差不大。
210
+
211
+ ### MinMPLookup 最小完美查找表的使用
212
+
213
+ 如果你有一个 `Value -> Key` 的查找需求(例如:根据`字体文件名`查找`字体家族名`,或者根据`城市`查找`国家`),且数据量较大,可以使用 `MinMPLookup`。它利用 MPHF 和差分编码极大地压缩了映射关系。
214
+
215
+ #### 场景
216
+
217
+ 假设你有以下映射:
218
+
219
+ ```js
220
+ const lookupMap = {
221
+ China: ["Beijing", "Shanghai", "Guangzhou"],
222
+ USA: ["New York", "Los Angeles"],
223
+ Japan: ["Tokyo"],
224
+ };
225
+ // 目标:输入 "Shanghai" -> 得到 "China"
226
+ ```
227
+
228
+ #### 创建查找字典
229
+
230
+ ```typescript
231
+ import { createMinMPLookupDict } from "min-mphash";
232
+
233
+ const lookupMap = {
234
+ China: ["Beijing", "Shanghai", "Guangzhou"],
235
+ USA: ["New York", "Los Angeles"],
236
+ Japan: ["Tokyo"],
237
+ };
238
+
239
+ // 生成压缩后的二进制字典
240
+ const lookupDictBin = createMinMPLookupDict(lookupMap, {
241
+ outputBinary: true,
242
+ enableCompression: true, // 启用内置 Gzip 压缩 (仅 Node/Bun 环境或支持 CompressionStream 的浏览器)
243
+ });
244
+
245
+ // 保存到文件
246
+ // fs.writeFileSync("lookup.bin", lookupDictBin);
247
+ ```
248
+
249
+ #### 查询
250
+
251
+ ```typescript
252
+ import { MinMPLookup } from "min-mphash";
253
+
254
+ // 加载字典
255
+ const lookup = await MinMPLookup.fromCompressed(lookupDictBin);
256
+ // 如果没有开启 enableCompression,使用 MinMPLookup.fromBinary(bin)
257
+
258
+ console.log(lookup.query("Shanghai")); // "China"
259
+ console.log(lookup.queryAll("New York")); // ["USA"]
260
+ console.log(lookup.query("Unknown City")); // null
261
+ console.log(lookup.keys()); // ["China", "USA", "Japan"]
262
+ ```
263
+
264
+ #### 校验模式 `onlySet`
265
+
266
+ 标准的最小完美哈希函数对于**不在集合中**的输入,也会返回一个范围内的索引。为了解决这个问题,`MinMPHash` 支持内置校验模式,确保让集合外的查找返回 `null`。
267
+
268
+ ```ts
269
+ const lookupDictBin = createMinMPLookupDict(lookupMap, {
270
+ onlySet: "8", // 启用 8-bit 校验模式
271
+ });
272
+ ```
273
+
274
+ ## Benchmark
275
+
276
+ ### MinMPHash 字典体积测试结果
277
+
278
+ ```
279
+
280
+ === MinMPHash Big Dataset Size Benchmark ===
281
+ Generating dataset of size 1000000...
282
+ Dataset size: 1000000 items
283
+
284
+ Dataset json size: 41836.25 KB
285
+ Dataset json gzip size: 6473.48 KB
286
+
287
+ ➤ Optimization Level 5
288
+ ┌──────────┬──────────────┬──────────────────────┬──────────────────────┬──────────────┬──────────────┐
289
+ │ OnlySet │ JSON Size │ Binary Size (Ratio) │ Gzip Size (Ratio) │ vs None │ Build Time │
290
+ ├──────────┼──────────────┼──────────────────────┼──────────────────────┼──────────────┼──────────────┤
291
+ │ none │ 979.18 KB │ 341.37 KB ( 35%) │ 268.36 KB ( 27%) │ 100.0 % │ 2502.35 ms │
292
+ │ 2 │ 1849.51 KB │ 585.38 KB ( 32%) │ 512.86 KB ( 28%) │ 171.5 % │ 2981.46 ms │
293
+ │ 4 │ 2721.75 KB │ 829.94 KB ( 30%) │ 757.49 KB ( 28%) │ 243.1 % │ 3109.38 ms │
294
+ │ 8 │ 4465.27 KB │ 1318.06 KB ( 30%) │ 1245.64 KB ( 28%) │ 386.1 % │ 3132.11 ms │
295
+ │ 16 │ 6672.22 KB │ 2293.96 KB ( 34%) │ 2222.43 KB ( 33%) │ 672.0 % │ 3559.02 ms │
296
+ │ 32 │ 11468.63 KB │ 4247.06 KB ( 37%) │ 4176.07 KB ( 36%) │ 1244.1 % │ 2900.32 ms │
297
+ └──────────┴──────────────┴──────────────────────┴──────────────────────┴──────────────┴──────────────┘
298
+
299
+ ```
300
+
301
+ ### MinMPLookup 字典体积测试结果
302
+
303
+ ```
304
+
305
+ === MinMPLookup Big Dataset Size Benchmark ===
306
+ Generating dataset of size 100000 values...
307
+ Dataset stats: 5000 keys, 100000 values
308
+
309
+ Dataset json size: 7577.04 KB
310
+ Dataset json gzip size: 5141.74 KB
311
+
312
+ ➤ Optimization Level 5
313
+ ┌──────────┬──────────────┬──────────────────────┬──────────────────────┬──────────────┬──────────────┐
314
+ │ OnlySet │ JSON Size │ Binary Size (Ratio) │ Gzip Size (Ratio) │ vs None │ Build Time │
315
+ ├──────────┼──────────────┼──────────────────────┼──────────────────────┼──────────────┼──────────────┤
316
+ │ none │ 709.67 KB │ 254.85 KB ( 36%) │ 199.59 KB ( 28%) │ 100.0 % │ 412.65 ms │
317
+ │ 2 │ 797.00 KB │ 279.23 KB ( 35%) │ 225.14 KB ( 28%) │ 109.6 % │ 393.94 ms │
318
+ │ 4 │ 884.32 KB │ 303.63 KB ( 34%) │ 248.92 KB ( 28%) │ 119.1 % │ 408.93 ms │
319
+ │ 8 │ 1058.92 KB │ 352.48 KB ( 33%) │ 297.58 KB ( 28%) │ 138.3 % │ 477.32 ms │
320
+ │ 16 │ 1406.98 KB │ 450.21 KB ( 32%) │ 395.21 KB ( 28%) │ 176.7 % │ 421.70 ms │
321
+ │ 32 │ 2104.73 KB │ 645.45 KB ( 31%) │ 591.02 KB ( 28%) │ 253.3 % │ 374.06 ms │
322
+ └──────────┴──────────────┴──────────────────────┴──────────────────────┴──────────────┴──────────────┘
323
+ ```
@@ -0,0 +1,140 @@
1
+ /**
2
+ * 最小完美哈希字典的原始数据结构。
3
+ *
4
+ * 通常通过 `createMinMPHashDict` 生成,并传递给 `MinMPHash` 构造函数。
5
+ */
6
+ export interface IMinMPHashDict {
7
+ n: number;
8
+ m: number;
9
+ seed0: number;
10
+ hashSeed?: number;
11
+ seedStream: Uint8Array;
12
+ bucketSizes: Uint8Array;
13
+ seedZeroBitmap?: Uint8Array;
14
+ fingerprints?: Uint8Array | Uint16Array | Uint32Array | number[];
15
+ validationMode: IValidationMode;
16
+ }
17
+ /** 验证模式,当字典在 onlySet 模式下启用 */
18
+ export type IValidationMode = "none" | "2" | "4" | "8" | "16" | "32";
19
+ export interface IMinMPHashDictOptions {
20
+ /**
21
+ * 启用校验模式,使 hash 函数仅对原始数据集中的数据有效。
22
+ *
23
+ * 如果传入不在数据集中的数据:
24
+ * - 启用后:hash 值返回 `-1`(有一定误判率)。
25
+ * - 未启用:hash 值会返回一个 [0, n-1] 之间的索引(即产生冲突)。
26
+ *
27
+ * **原理**:字典会额外存储每条数据的指纹(Fingerprint)。这会增加字典体积。
28
+ *
29
+ * **误判率说明**:
30
+ * - `"2"` - 2-bit 指纹 (0.25 byte/key) ~25% 误判率
31
+ * - `"4"` - 4-bit 指纹 (0.5 byte/key) ~6.25% 误判率
32
+ * - `"8"` - 8-bit 指纹 (1 byte/key) ~0.39% 误判率
33
+ * - `"16"` - 16-bit 指纹 (2 bytes/key) ~0.0015% 误判率
34
+ * - `"32"` - 32-bit 指纹 (4 bytes/key) ~0.00000002% 误判率
35
+ *
36
+ * @default "none" (或 false)
37
+ * @example
38
+ * onlySet: "8" // 启用 8-bit 校验,平衡体积与准确性
39
+ */
40
+ onlySet?: boolean | IValidationMode;
41
+ /**
42
+ * 字典优化级别 [1-10]。
43
+ *
44
+ * level 越大,字典体积越小,但构建(Build)时间越长。
45
+ *
46
+ * @example
47
+ * - level 1: 快速构建,体积较大 (约 112 KB)
48
+ * - level 5: 默认平衡点 (约 24 KB)
49
+ * - level 10: 极致压缩,构建极慢 (约 17 KB)
50
+ * @default 5
51
+ */
52
+ level?: number;
53
+ /**
54
+ * 是否输出二进制 CBOR 格式的字典。
55
+ *
56
+ * 如果为 `true`,`createMinMPHashDict` 将返回 `Uint8Array`。
57
+ * @default false
58
+ */
59
+ outputBinary?: boolean;
60
+ /**
61
+ * 是否启用 Gzip 压缩。
62
+ *
63
+ * **注意**:仅当 `outputBinary` 为 `true` 时有效。
64
+ * 启用后返回 `Promise<Uint8Array>`,需使用 `MinMPHash.fromCompressed()` 加载。
65
+ * @default false
66
+ */
67
+ enableCompression?: boolean;
68
+ }
69
+ /**
70
+ * 创建最小完美哈希 (MPHF) 字典。
71
+ */
72
+ export declare function createMinMPHashDict(dataSet: string[], options?: IMinMPHashDictOptions & {
73
+ outputBinary?: false;
74
+ }): IMinMPHashDict;
75
+ /**
76
+ * 创建最小完美哈希 (MPHF) 字典。
77
+ *
78
+ * @param options.outputBinary 输出二进制格式
79
+ */
80
+ export declare function createMinMPHashDict(dataSet: string[], options: IMinMPHashDictOptions & {
81
+ outputBinary: true;
82
+ enableCompression?: false;
83
+ }): Uint8Array;
84
+ /**
85
+ * 创建最小完美哈希 (MPHF) 字典。
86
+ *
87
+ * @param options.outputBinary 输出二进制格式
88
+ * @param options.enableCompression 启用压缩
89
+ */
90
+ export declare function createMinMPHashDict(dataSet: string[], options: IMinMPHashDictOptions & {
91
+ outputBinary: true;
92
+ enableCompression: true;
93
+ }): Promise<Uint8Array>;
94
+ /**
95
+ * 最小完美哈希 (Minimal Perfect Hash) 查询类。
96
+ *
97
+ * 该类用于加载由 `createMinMPHashDict` 生成的字典,并提供高效的哈希查询。
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const dict = createMinMPHashDict(["apple", "banana"]);
102
+ * const mph = new MinMPHash(dict);
103
+ * console.log(mph.hash("apple")); // 0 或 1
104
+ * ```
105
+ */
106
+ export declare class MinMPHash {
107
+ n: number;
108
+ private m;
109
+ private seed0;
110
+ private hashSeed;
111
+ private offsets;
112
+ private seeds;
113
+ private validationMode;
114
+ private fingerprints;
115
+ private static readonly FP_SEED;
116
+ /**
117
+ * 从经过 Gzip 压缩的二进制数据加载字典。
118
+ *
119
+ * @param data 压缩后的 Uint8Array 数据
120
+ * @returns MinMPHash 实例
121
+ */
122
+ static fromCompressed(data: Uint8Array): Promise<MinMPHash>;
123
+ /**
124
+ * 构造函数。
125
+ *
126
+ * @param dict 字典对象 (`IMinMPHashDict`) 或二进制 CBOR 数据 (`Uint8Array`)
127
+ */
128
+ constructor(dict: IMinMPHashDict | Uint8Array);
129
+ /**
130
+ * 计算输入字符串的哈希值。
131
+ *
132
+ * @param input 要查询的字符串
133
+ * @returns
134
+ * - 如果字符串在原始数据集中:返回其唯一的索引 `[0, n-1]`。
135
+ * - 如果字符串不在数据集中:
136
+ * - 启用了 `onlySet`:返回 `-1` (有极低概率误判为有效索引)。
137
+ * - 未启用 `onlySet`:返回一个冲突的索引 `[0, n-1]`。
138
+ */
139
+ hash(input: string): number;
140
+ }
@@ -0,0 +1,115 @@
1
+ import { IValidationMode } from "./MinMPHash";
2
+ export type ILookupMap = Record<string, string[]>;
3
+ export interface IMinMPLookupDict {
4
+ mmpHashDictBin: Uint8Array;
5
+ keys: string[];
6
+ /**
7
+ * Mode 0: Key -> Hashes (Original, for M-to-N)
8
+ * 存储每个 Key 对应的 Value Hash 列表。
9
+ * 这是一个稀疏的映射结构,用于支持 1-to-Many (Value -> Keys) 的反向查找。
10
+ *
11
+ * 结构: KeyIndex -> Sorted Hash List
12
+ */
13
+ keyToHashes?: Uint32Array[];
14
+ /**
15
+ * Mode 1: Value -> Key (Direct 1-to-1)
16
+ * 存储每个 Value Hash 对应的 Key Index。
17
+ * 这是一个紧凑的数组,长度为 TotalValues。
18
+ *
19
+ * 结构: ValueHash -> KeyIndex (Bit-packed)
20
+ */
21
+ valueToKeyIndexes?: Uint8Array;
22
+ bitsPerKey?: number;
23
+ /**
24
+ * Mode 2: Hybrid (Mostly 1-to-1, with some collisions)
25
+ * Used when valueToKeyIndexes is present.
26
+ * If a value in valueToKeyIndexes equals `keys.length`, it means there are multiple keys.
27
+ * This map stores the actual keys for those collision cases.
28
+ *
29
+ * Structure: ValueHash -> KeyIndex[]
30
+ */
31
+ collisionMap?: Map<number, number[]>;
32
+ }
33
+ export interface IMinMPLookupDictOptions {
34
+ /**
35
+ * 字典优化级别 [1-10]。
36
+ * @default 5
37
+ */
38
+ level?: number;
39
+ outputBinary?: boolean;
40
+ enableCompression?: boolean;
41
+ /**
42
+ * 启用校验模式,使 hash 函数仅对原始数据集中的数据有效。
43
+ * @default "8"
44
+ */
45
+ onlySet?: boolean | IValidationMode;
46
+ }
47
+ /**
48
+ * 创建 MinMPLookup 字典
49
+ * 把一个普通的查找表 Record<string, string[]> 转换为 IMinMPLookupDict,减小体积并且完成快速查询
50
+ *
51
+ * 通过 MinMPLookup 配合字典,可以实现输入 lookupMap 中任意 values 查找到对应的 key
52
+ *
53
+ * @param lookupMap 普通查找表
54
+ */
55
+ export declare function createMinMPLookupDict(lookupMap: ILookupMap, options?: IMinMPLookupDictOptions & {
56
+ outputBinary?: false;
57
+ enableCompression?: false;
58
+ }): IMinMPLookupDict;
59
+ export declare function createMinMPLookupDict(lookupMap: ILookupMap, options: IMinMPLookupDictOptions & {
60
+ outputBinary?: false;
61
+ enableCompression: true;
62
+ }): Promise<IMinMPLookupDict>;
63
+ export declare function createMinMPLookupDict(lookupMap: ILookupMap, options: IMinMPLookupDictOptions & {
64
+ outputBinary: true;
65
+ enableCompression?: false;
66
+ }): Uint8Array;
67
+ export declare function createMinMPLookupDict(lookupMap: ILookupMap, options: IMinMPLookupDictOptions & {
68
+ outputBinary: true;
69
+ enableCompression: true;
70
+ }): Promise<Uint8Array>;
71
+ /**
72
+ * Serializes the lookup dictionary to a binary format.
73
+ */
74
+ export declare function serializeMinMPLookupDict(dict: IMinMPLookupDict): Uint8Array;
75
+ /**
76
+ * MinMPLookup 查找表类
77
+ * 用来实现基于 IMinMPLookupDict 的快速查询
78
+ *
79
+ * @example
80
+ * ```js
81
+ *
82
+ * let lookupMap = {
83
+ * "China": ["Beijing", "Shanghai", "Guangzhou"],
84
+ * "USA": ["New York", "Los Angeles", "Chicago"],
85
+ * "Japan": ["Tokyo", "Osaka", "Kyoto"]
86
+ * }
87
+ *
88
+ * let dict = createMinMPLookupDict(lookupMap);
89
+ * let lookup = new MinMPLookup(dict);
90
+ *
91
+ * lookup.query("Beijing"); // "China"
92
+ *
93
+ *```
94
+ */
95
+ export declare class MinMPLookup {
96
+ private dict;
97
+ private mph;
98
+ private _invertedIndex;
99
+ static fromCompressed(data: Uint8Array): Promise<MinMPLookup>;
100
+ static fromBinary(data: Uint8Array): MinMPLookup;
101
+ constructor(dict: IMinMPLookupDict);
102
+ private buildInvertedIndex;
103
+ /**
104
+ * 查找 value 对应的第一个 key
105
+ */
106
+ query(value: string): string | null;
107
+ /**
108
+ * 获取拥有 value 的所有 keys
109
+ */
110
+ queryAll(value: string): string[] | null;
111
+ /**
112
+ * 获取所有的 keys 列表
113
+ */
114
+ keys(): string[];
115
+ }
@@ -0,0 +1,4 @@
1
+ export { createMinMPHashDict, MinMPHash } from "./MinMPHash";
2
+ export type { IMinMPHashDict, IValidationMode } from "./MinMPHash";
3
+ export { createMinMPLookupDict, MinMPLookup } from "./MinMPLookup";
4
+ export type { IMinMPLookupDict, IMinMPLookupDictOptions } from "./MinMPLookup";