semantic-typescript 0.5.3 → 0.6.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/dist/asynchronous/collector.d.ts +231 -0
- package/dist/asynchronous/collector.js +800 -0
- package/dist/asynchronous/semantic.d.ts +257 -0
- package/dist/asynchronous/semantic.js +1853 -0
- package/dist/factory.d.ts +71 -37
- package/dist/factory.js +443 -262
- package/dist/guard.d.ts +24 -14
- package/dist/guard.js +73 -19
- package/dist/hook.d.ts +6 -6
- package/dist/hook.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/optional.d.ts +2 -2
- package/dist/symbol.d.ts +19 -10
- package/dist/symbol.js +19 -10
- package/dist/synchronous/collector.d.ts +232 -0
- package/dist/{collector.js → synchronous/collector.js} +160 -151
- package/dist/{semantic.d.ts → synchronous/semantic.d.ts} +111 -120
- package/dist/{semantic.js → synchronous/semantic.js} +299 -337
- package/dist/utility.d.ts +7 -1
- package/dist/utility.js +1 -0
- package/package.json +1 -1
- package/readme.cn.md +158 -697
- package/readme.de.md +163 -432
- package/readme.es.md +163 -433
- package/readme.fr.md +162 -444
- package/readme.jp.md +162 -442
- package/readme.kr.md +161 -430
- package/readme.md +157 -1009
- package/readme.ru.md +161 -426
- package/readme.tw.md +161 -436
- package/dist/collector.d.ts +0 -236
- package/dist/main.d.ts +0 -1
- package/dist/main.js +0 -4
- package/dist/map.d.ts +0 -76
- package/dist/map.js +0 -245
- package/dist/node.d.ts +0 -182
- package/dist/node.js +0 -918
- package/dist/set.d.ts +0 -19
- package/dist/set.js +0 -65
- package/dist/tree.d.ts +0 -82
- package/dist/tree.js +0 -257
package/readme.cn.md
CHANGED
|
@@ -1,753 +1,214 @@
|
|
|
1
|
-
# Semantic-TypeScript
|
|
1
|
+
# Semantic-TypeScript:一款范式转换的流处理库
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 简介
|
|
4
|
+
Semantic-TypeScript 代表了流处理技术的一项重大进步,它综合了 JavaScript GeneratorFunctions、Java Streams 和数据库索引范式中最有效的概念。其基础设计原则的核心是通过复杂的惰性求值和智能索引构建极其高效的数据处理管道。该库提供了一个严格类型安全、函数式纯正的流式操作体验,专门为现代 TypeScript 和 JavaScript 开发而设计。
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
与传统的同步处理架构相比,Semantic-TypeScript 实现了一个统一模型,优雅地处理同步(Iterable)和异步(AsyncIterable)数据源。在流生成过程中,数据的流动和终止由回调机制精确控制,使库能够以超凡的优雅处理:
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- 具有确定性控制的实时数据流(DOM 事件、WebSockets、时间间隔)
|
|
9
|
+
- 通过内存高效的惰性管道处理大规模数据集
|
|
10
|
+
- 通过流畅、声明式的 API 进行复杂的数据转换
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
该库的创新方法从根本上重新构想了开发者与数据序列交互的方式,在一个单一、内聚的包中同时提供了前所未有的性能特性和开发者体验。
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* **具有一致性和可靠性保证的异步数据源**
|
|
14
|
+
## 核心理念:定义与执行的分离
|
|
15
|
+
Semantic-TypeScript 的一个关键架构洞见是清晰地分离流的定义和执行:
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
- **Semantic<E>**:一个不可变的、惰性的数据转换管道蓝图。它定义了将执行哪些操作(过滤、映射等)
|
|
18
|
+
- **Collectable<E>**:一个已实例化的、可执行的流视图。它是从 Semantic 获取的,并提供所有终端操作(收集、遍历等)来执行管道并生成结果
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
这种分离强化了清晰的心智模型,并释放了强大的优化能力,例如选择 UnorderedCollectable 来跳过不必要的排序以实现最大速度。
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
## 为什么选择 Semantic-TypeScript?
|
|
23
|
+
为数据流处理选择合适的库需要在性能、类型安全性和表达能力之间取得平衡。Semantic-TypeScript 的设计旨在所有这些维度上都表现出色。
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
### 1. 适用于所有数据序列的统一、类型安全范式
|
|
26
|
+
它为处理任何数据序列(无论是静态数组、实时事件还是异步块)提供了一致的声明式 API,同时利用 TypeScript 的全部功能确保端到端的类型安全。这消除了一整类运行时错误,并将流操作转变为可预测的、经过编译器验证的活动。
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
### 2. 以智能惰性求值实现的不妥协性能
|
|
29
|
+
该库的核心建立在惰性求值之上。诸如过滤器、映射和扁平映射等操作仅仅是组合一个处理管道;直到调用终端操作时,实际工作才会执行。这结合了短路功能(通过限制、任何匹配或自定义中断回调),允许处理提前停止,从而极大地提高了大型或无限流的处理效率。
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* **`Semantic<E>`**:表示抽象的、惰性的流定义——数据转换的“蓝图”。它是不可变且可组合的。
|
|
30
|
-
* **`Collectable<E>`**:表示一个物化的、可执行的流视图,提供所有终端操作。
|
|
31
|
+
### 3. `Collector<E, A, R>` 模式的强大之处
|
|
32
|
+
受 Java 启发,收集器模式是灵活性的引擎。它将如何累积流元素的规范与流本身的执行解耦。该库为日常任务提供了一组丰富的内置收集器(toArray、groupBy、summate 等),同时使实现您自己复杂的、可重用的归约逻辑变得非常简单。这比固定的一组终端方法要强大和可组合得多。
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
### 4. 对现代 Web 和异步数据的一流支持
|
|
35
|
+
Semantic-TypeScript 专为当代开发而设计。它为现代网络源提供了本机工厂方法:
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
- `useFrom(iterable)`, `useRange()` 用于静态数据
|
|
38
|
+
- `useInterval()`, `useAnimationFrame()` 用于基于时间的流
|
|
39
|
+
- `useBlob()` 用于分块二进制数据处理
|
|
40
|
+
- `useWebSocket()`, `useDocument()`, `useWindow()` 用于实时事件流
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* `from(iterable)`、`range()` 用于静态数据。
|
|
40
|
-
* `interval()`、`animationFrame()` 用于基于时间的流。
|
|
41
|
-
* `blob()` 用于分块二进制数据处理。
|
|
42
|
-
* `websocket()` 用于实时消息流。
|
|
43
|
-
它对 `Iterable` 和 `AsyncIterable` 协议的基础支持意味着它用相同的优雅 API 处理同步和异步数据流。
|
|
42
|
+
### 5. 超越基本聚合:内置统计分析
|
|
43
|
+
超越简单的求和与平均。该库提供了专用的 NumericStatistics 和 BigIntStatistics 接口,可以直接从您的流中即时访问高级统计指标——方差、标准差、中位数、偏度和峰度。这将复杂的数据分析变成了一行代码。
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* **全面的实用工具套件**:开箱即用,包含必要的守卫(`isOptional`、`isSemantic`)、类型安全的实用程序(`useCompare`、`useTraverse`)和函数式接口。
|
|
51
|
-
* **`Optional<T>` 集成**:安全地建模值的缺失,消除查找操作中的空指针问题。
|
|
52
|
-
* **性能指南**:文档清晰地指导您何时使用 `toUnordered()`(追求最大速度)与 `toOrdered()`(当顺序重要时)。
|
|
53
|
-
|
|
54
|
-
#### 8. **健壮、面向社区的基础**
|
|
55
|
-
作为一个托管在 **GitHub** 上并通过 **npm** 分发的开源库,它专为实际应用而构建。详尽的文档,附带时间和空间复杂度注解及实际示例,降低了学习曲线,并为性能敏感的应用提供了清晰性。
|
|
56
|
-
|
|
57
|
-
**总而言之,如果您寻求一个严格设计、类型安全且高性能的流处理库,它将企业级数据转换模式的力量带入 TypeScript 生态系统,同时又不妥协于现代网络开发的惯用语法和需求,请选择 Semantic-TypeScript。**
|
|
45
|
+
### 6. 为开发者体验而设计
|
|
46
|
+
- **流畅、可链式调用的 API**:将复杂的数据管道编写为可读的、顺序链
|
|
47
|
+
- **全面的工具套件**:包含必要的守卫(isFunction, isIterable)、实用程序(useCompare, useTraverse)和函数式接口
|
|
48
|
+
- **Optional<T> 集成**:安全地建模值的缺失,消除了空指针的担忧
|
|
49
|
+
- **性能指南**:清楚地指导何时使用无序集合以获得速度,何时使用有序集合以保持序列
|
|
58
50
|
|
|
59
51
|
## 安装
|
|
60
|
-
|
|
61
52
|
```bash
|
|
62
53
|
npm install semantic-typescript
|
|
63
54
|
```
|
|
64
55
|
|
|
65
|
-
##
|
|
66
|
-
|
|
67
|
-
| 类型 | 描述 |
|
|
68
|
-
|------|-------------|
|
|
69
|
-
| `Invalid<T>` | 继承自 `null` 或 `undefined` 的类型 |
|
|
70
|
-
| `Valid<T>` | 排除 `null` 和 `undefined` 的类型 |
|
|
71
|
-
| `MaybeInvalid<T>` | 可能为 `null` 或 `undefined` 的类型 |
|
|
72
|
-
| `Primitive` | 原始类型的集合 |
|
|
73
|
-
| `MaybePrimitive<T>` | 可能是原始类型的类型 |
|
|
74
|
-
| `OptionalSymbol` | `Optional` 类的 Symbol 标识符 |
|
|
75
|
-
| `SemanticSymbol` | `Semantic` 类的 Symbol 标识符 |
|
|
76
|
-
| `CollectorsSymbol` | `Collector` 类的 Symbol 标识符 |
|
|
77
|
-
| `CollectableSymbol` | `Collectable` 类的 Symbol 标识符 |
|
|
78
|
-
| `OrderedCollectableSymbol` | `OrderedCollectable` 类的 Symbol 标识符 |
|
|
79
|
-
| `WindowCollectableSymbol` | `WindowCollectable` 类的 Symbol 标识符 |
|
|
80
|
-
| `StatisticsSymbol` | `Statistics` 类的 Symbol 标识符 |
|
|
81
|
-
| `NumericStatisticsSymbol` | `NumericStatistics` 类的 Symbol 标识符 |
|
|
82
|
-
| `BigIntStatisticsSymbol` | `BigIntStatistics` 类的 Symbol 标识符 |
|
|
83
|
-
| `UnorderedCollectableSymbol` | `UnorderedCollectable` 类的 Symbol 标识符 |
|
|
84
|
-
|
|
85
|
-
## 函数式接口
|
|
86
|
-
|
|
87
|
-
| 接口 | 描述 |
|
|
88
|
-
|-----------|-------------|
|
|
89
|
-
| `Runnable` | 无参数无返回值的函数 |
|
|
90
|
-
| `Supplier<R>` | 无参数并返回 `R` 的函数 |
|
|
91
|
-
| `Functional<T, R>` | 单参数转换函数 |
|
|
92
|
-
| `BiFunctional<T, U, R>` | 双参数转换函数 |
|
|
93
|
-
| `TriFunctional<T, U, V, R>` | 三参数转换函数 |
|
|
94
|
-
| `Predicate<T>` | 单参数谓词函数 |
|
|
95
|
-
| `BiPredicate<T, U>` | 双参数谓词函数 |
|
|
96
|
-
| `TriPredicate<T, U, V>` | 三参数谓词函数 |
|
|
97
|
-
| `Consumer<T>` | 单参数消费者函数 |
|
|
98
|
-
| `BiConsumer<T, U>` | 双参数消费者函数 |
|
|
99
|
-
| `TriConsumer<T, U, V>` | 三参数消费者函数 |
|
|
100
|
-
| `Comparator<T>` | 双参数比较函数 |
|
|
101
|
-
| `Generator<T>` | 生成器函数(核心与基础) |
|
|
56
|
+
## 核心概念实践
|
|
102
57
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
let predicate: Predicate<number> = (n: number): boolean => n > 0;
|
|
106
|
-
let mapper: Functional<string, number> = (text: string): number => text.length;
|
|
107
|
-
let comparator: Comparator<number> = (a: number, b: number): number => a - b;
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## 类型守卫
|
|
111
|
-
|
|
112
|
-
| 函数 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
113
|
-
|------|------|------------|------------|
|
|
114
|
-
| `validate<T>(t: MaybeInvalid<T>): t is T` | 验证值不为 null 或 undefined | O(1) | O(1) |
|
|
115
|
-
| `invalidate<T>(t: MaybeInvalid<T>): t is null \| undefined` | 验证值为 null 或 undefined | O(1) | O(1) |
|
|
116
|
-
| `isBoolean(t: unknown): t is boolean` | 检查是否为布尔值 | O(1) | O(1) |
|
|
117
|
-
| `isString(t: unknown): t is string` | 检查是否为字符串 | O(1) | O(1) |
|
|
118
|
-
| `isNumber(t: unknown): t is number` | 检查是否为数字 | O(1) | O(1) |
|
|
119
|
-
| `isFunction(t: unknown): t is Function` | 检查是否为函数 | O(1) | O(1) |
|
|
120
|
-
| `isObject(t: unknown): t is object` | 检查是否为对象 | O(1) | O(1) |
|
|
121
|
-
| `isSymbol(t: unknown): t is symbol` | 检查是否为 Symbol | O(1) | O(1) |
|
|
122
|
-
| `isBigint(t: unknown): t is bigint` | 检查是否为 BigInt | O(1) | O(1) |
|
|
123
|
-
| `isPrimitive(t: unknown): t is Primitive` | 检查是否为原始类型 | O(1) | O(1) |
|
|
124
|
-
| `isIterable(t: unknown): t is Iterable<unknown>` | 检查是否为可迭代对象 | O(1) | O(1) |
|
|
125
|
-
| `isOptional(t: unknown): t is Optional<unknown>` | 检查是否为 Optional 实例 | O(1) | O(1) |
|
|
126
|
-
| `isSemantic(t: unknown): t is Semantic<unknown>` | 检查是否为 Semantic 实例 | O(1) | O(1) |
|
|
127
|
-
| `isCollector(t: unknown): t is Collector<unknown, unknown, unknown>` | 检查是否为 Collector 实例 | O(1) | O(1) |
|
|
128
|
-
| `isCollectable(t: unknown): t is Collectable<unknown>` | 检查是否为 Collectable 实例 | O(1) | O(1) |
|
|
129
|
-
| `isOrderedCollectable(t: unknown): t is OrderedCollectable<unknown>` | 检查是否为 OrderedCollectable 实例 | O(1) | O(1) |
|
|
130
|
-
| `isWindowCollectable(t: unknown): t is WindowCollectable<unknown>` | 检查是否为 WindowCollectable 实例 | O(1) | O(1) |
|
|
131
|
-
| `isUnorderedCollectable(t: unknown): t is UnorderedCollectable<unknown>` | 检查是否为 UnorderedCollectable 实例 | O(1) | O(1) |
|
|
132
|
-
| `isStatistics(t: unknown): t is Statistics<unknown, number \| bigint>` | 检查是否为 Statistics 实例 | O(1) | O(1) |
|
|
133
|
-
| `isNumericStatistics(t: unknown): t is NumericStatistics<unknown>` | 检查是否为 NumericStatistics 实例 | O(1) | O(1) |
|
|
134
|
-
| `isBigIntStatistics(t: unknown): t is BigIntStatistics<unknown>` | 检查是否为 BigIntStatistics 实例 | O(1) | O(1) |
|
|
135
|
-
| `isPromise(t: unknown): t is Promise<unknown>` | 检查是否为 Promise 对象 | O(1) | O(1) |
|
|
136
|
-
| `isAsyncFunction(t: unknown): t is AsyncFunction` | 检查是否为 AsyncFunction | O(1) | O(1) |
|
|
137
|
-
| `isGeneratorFunction(t: unknown): t is GeneratorFunction` | 检查是否为 GeneratorFunction | O(1) | O(1) |
|
|
138
|
-
| `isAsyncGeneratorFunction(t: unknown): t is AsyncGeneratorFunction` | 检查是否为 AsyncGeneratorFunction | O(1) | O(1) |
|
|
58
|
+
### 1. 创建流 (Semantic)
|
|
59
|
+
可以使用工厂函数从各种源创建流。
|
|
139
60
|
|
|
140
61
|
```typescript
|
|
141
|
-
|
|
142
|
-
let value: unknown = "hello";
|
|
143
|
-
|
|
144
|
-
if (isString(value)) {
|
|
145
|
-
console.log(value.length); // 类型安全,value 被推断为 string
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (isOptional(someValue)) {
|
|
149
|
-
someValue.ifPresent((value): void => console.log(value));
|
|
150
|
-
}
|
|
62
|
+
import { useFrom, useInterval, useDocument } from 'semantic-typescript';
|
|
151
63
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
for(let item of value){
|
|
155
|
-
console.log(item);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## 工具函数
|
|
64
|
+
// 从静态数组创建
|
|
65
|
+
const staticStream = useFrom([1, 2, 3, 4, 5]);
|
|
161
66
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
| `useTraverse(t, callback)` | 深度遍历对象,不处理循环引用 | O(n) | O(1) |
|
|
167
|
-
| `useToNumber(t: unknown): number` | 将值转换为数字 | O(1) | O(1) |
|
|
168
|
-
| `useToBigInt(t: unknown): bigint` | 将值转换为 BigInt | O(1) | O(1) |
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
// 工具函数使用示例
|
|
172
|
-
let numbers: Array<number> = [3, 1, 4, 1, 5];
|
|
173
|
-
numbers.sort(useCompare); // [1, 1, 3, 4, 5]
|
|
174
|
-
|
|
175
|
-
let randomNum: number = useRandom(42); // 基于种子的随机数
|
|
176
|
-
|
|
177
|
-
let o = {
|
|
178
|
-
a: 1,
|
|
179
|
-
b: {
|
|
180
|
-
c: 2,
|
|
181
|
-
d: o
|
|
182
|
-
},
|
|
183
|
-
c: [1, 3, 5, o],
|
|
184
|
-
e: undefined,
|
|
185
|
-
f: null
|
|
186
|
-
};
|
|
187
|
-
useTraverse(o, (value, key): boolean => {
|
|
188
|
-
console.log(key, value);
|
|
189
|
-
/*
|
|
190
|
-
a 1
|
|
191
|
-
c 2
|
|
192
|
-
1 3 5
|
|
193
|
-
循环引用、undefined 和 null 值不会被遍历。
|
|
194
|
-
*/
|
|
195
|
-
return true; // 返回 true 以继续遍历
|
|
67
|
+
// 从异步生成器创建
|
|
68
|
+
const asyncStream = useFrom(async function*() {
|
|
69
|
+
yield 1;
|
|
70
|
+
yield 2;
|
|
196
71
|
});
|
|
197
72
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
};
|
|
201
|
-
let resolvedNumber: number = useToNumber(toBeResolved); // 5
|
|
202
|
-
let resolvedBigInt: bigint = useToBigInt(toBeResolved); // 5n
|
|
203
|
-
```
|
|
73
|
+
// 一个基于时间的流
|
|
74
|
+
const tickStream = useInterval(1000); // 每秒发射一次
|
|
204
75
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
### Optional 工厂方法
|
|
208
|
-
|
|
209
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
210
|
-
|------|------|------------|------------|
|
|
211
|
-
| `Optional.empty<T>()` | 创建一个空的 Optional | O(1) | O(1) |
|
|
212
|
-
| `Optional.of<T>(value)` | 创建一个包含值的 Optional | O(1) | O(1) |
|
|
213
|
-
| `Optional.ofNullable<T>(value)` | 创建一个可能为空的 Optional | O(1) | O(1) |
|
|
214
|
-
| `Optional.ofNonNull<T>(value)` | 创建一个非 null 的 Optional | O(1) | O(1) |
|
|
215
|
-
|
|
216
|
-
```typescript
|
|
217
|
-
// Optional 使用示例
|
|
218
|
-
let empty: Optional<number> = Optional.empty();
|
|
219
|
-
let present: Optional<number> = Optional.of(42);
|
|
220
|
-
let nullable: Optional<string> = Optional.ofNullable<string>(null);
|
|
221
|
-
let nonNull: Optional<string> = Optional.ofNonNull("hello");
|
|
222
|
-
|
|
223
|
-
present.ifPresent((value: number): void => console.log(value)); // 输出 42
|
|
224
|
-
console.log(empty.get(100)); // 输出 100
|
|
76
|
+
// 一个 DOM 事件流(参见下面的重要说明)
|
|
77
|
+
const clickStream = useDocument('click');
|
|
225
78
|
```
|
|
226
79
|
|
|
227
|
-
###
|
|
228
|
-
|
|
229
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
230
|
-
|------|------|------------|------------|
|
|
231
|
-
| `Collector.full(identity, accumulator, finisher)` | 创建一个完整收集器 | O(1) | O(1) |
|
|
232
|
-
| `Collector.shortable(identity, interruptor, accumulator, finisher)` | 创建一个可中断的收集器 | O(1) | O(1) |
|
|
233
|
-
| `useAnyMatch<E>(predicate)` | 创建一个短路的收集器,如果任何元素匹配谓词则返回 true | O(n) | O(1) |
|
|
234
|
-
| `useAllMatch<E>(predicate)` | 创建一个短路的收集器,如果所有元素匹配谓词则返回 true | O(n) | O(1) |
|
|
235
|
-
| `useCollect<E, A, R>(identity, accumulator, finisher)` | 使用 identity、accumulator、finisher 创建一个完整收集器 | O(1) | O(1) |
|
|
236
|
-
| `useCollect<E, A, R>(identity, interruptor, accumulator, finisher)` | 使用 identity、interruptor、accumulator、finisher 创建一个可短路的收集器 | O(1) | O(1) |
|
|
237
|
-
| `useCount<E>()` | 创建一个统计元素数量的完整收集器 | O(n) | O(1) |
|
|
238
|
-
| `useError<E>()` | 创建一个打印错误的收集器 | O(n) | O(1) |
|
|
239
|
-
| `useError<E>(accumulator)` | 创建一个打印累计错误的收集器 | O(n) | O(1) |
|
|
240
|
-
| `useError<E>(prefix, accumulator, suffix)` | 创建一个打印带前缀和后缀累计错误的收集器 | O(n) | O(1) |
|
|
241
|
-
| `useFindFirst<E>()` | 创建一个返回第一个元素的短路的收集器 | O(n) | O(1) |
|
|
242
|
-
| `useFindAny<E>()` | 创建一个返回任意元素的短路的收集器 | O(n) | O(1) |
|
|
243
|
-
| `useFindLast<E>()` | 创建一个返回最后一个元素的完整收集器 | O(n) | O(1) |
|
|
244
|
-
| `useFindMaximum<E>()` | 创建一个返回最大元素的完整收集器 | O(n) | O(1) |
|
|
245
|
-
| `useFindMaximum<E>(comparator?)` | 创建一个返回最大元素的完整收集器 | O(n) | O(1) |
|
|
246
|
-
| `useFindMinimum<E>()` | 创建一个返回最小元素的完整收集器 | O(n) | O(1) |
|
|
247
|
-
| `useFindMinimum<E>(comparator?)` | 创建一个返回最小元素的完整收集器 | O(n) | O(1) |
|
|
248
|
-
| `useForEach<E>(action)` | 创建一个为每个元素执行操作的完整收集器 | O(n) | O(1) |
|
|
249
|
-
| `useNoneMatch<E>(predicate)` | 创建一个短路的收集器,如果没有元素匹配谓词则返回 true | O(n) | O(1) |
|
|
250
|
-
| `useGroup<E, K>(classifier)` | 创建一个按分类器键对元素分组的完整收集器 | O(n) | O(n) |
|
|
251
|
-
| `useGroupBy<E, K, V>(keyExtractor, valueExtractor)` | 创建一个按提取的键对元素分组,并提取值的完整收集器 | O(n) | O(n) |
|
|
252
|
-
| `useJoin<E>()` | 创建一个使用默认格式将元素连接成字符串的完整收集器 | O(n) | O(1) |
|
|
253
|
-
| `useJoin<E>(delimiter)` | 创建一个使用分隔符连接元素的完整收集器 | O(n) | O(1) |
|
|
254
|
-
| `useJoin<E>(prefix, delimiter, suffix)` | 创建一个使用前缀、分隔符、后缀连接元素的完整收集器 | O(n) | O(1) |
|
|
255
|
-
| `useJoin<E>(prefix, accumulator, suffix)` | 创建一个通过自定义累加器连接元素的完整收集器 | O(n) | O(1) |
|
|
256
|
-
| `useLog<E>()` | 创建一个使用默认格式将元素记录到控制台的完整收集器 | O(n) | O(1) |
|
|
257
|
-
| `useLog<E>(accumulator)` | 创建一个通过自定义累加器记录元素的完整收集器 | O(n) | O(1) |
|
|
258
|
-
| `useLog<E>(prefix, accumulator, suffix)` | 创建一个通过累加器记录元素,并带前缀/后缀的完整收集器 | O(n) | O(1) |
|
|
259
|
-
| `usePartition<E>(count)` | 创建一个将元素分割为指定大小块的完整收集器 | O(n) | O(n) |
|
|
260
|
-
| `usePartitionBy<E>(classifier)` | 创建一个按分类器结果对元素分区的完整收集器 | O(n) | O(n) |
|
|
261
|
-
| `useReduce<E>(accumulator)` | 创建一个无初始值归约元素的完整收集器 | O(n) | O(1) |
|
|
262
|
-
| `useReduce<E>(identity, accumulator)` | 创建一个带有初始值归约元素的完整收集器 | O(n) | O(1) |
|
|
263
|
-
| `useReduce<E, R>(identity, accumulator, finisher)` | 创建一个带有 identity、accumulator、finisher 归约元素的完整收集器 | O(n) | O(1) |
|
|
264
|
-
| `useToArray<E>()` | 创建一个将元素收集到数组的完整收集器 | O(n) | O(n) |
|
|
265
|
-
| `useToMap<E, K, V>(keyExtractor, valueExtractor)` | 创建一个将元素收集到 Map 的完整收集器 | O(n) | O(n) |
|
|
266
|
-
| `useToSet<E>()` | 创建一个将元素收集到 Set 的完整收集器 | O(n) | O(n) |
|
|
267
|
-
| `useWrite<E, S>(stream)` | 创建一个将元素写入流的完整收集器 | O(n) | O(1) |
|
|
268
|
-
| `useWrite<E, S>(stream, accumulator)` | 创建一个通过自定义累加器将元素写入流的完整收集器 | O(n) | O(1) |
|
|
269
|
-
| `useNumericAverage<E>(mapper)` | 创建一个通过映射器计算数字平均值的完整收集器 | O(n) | O(1) |
|
|
270
|
-
| `useNumericAverage<E>()` | 创建一个计算数字平均值的完整收集器 | O(n) | O(1) |
|
|
271
|
-
| `useBigIntAverage<E>(mapper)` | 创建一个通过映射器计算 BigInt 平均值的完整收集器 | O(n) | O(1) |
|
|
272
|
-
| `useBigIntAverage<E>()` | 创建一个计算 BigInt 平均值的完整收集器 | O(n) | O(1) |
|
|
273
|
-
| `useFrequency<E>()` | 创建一个统计元素频率的完整收集器 | O(n) | O(n) |
|
|
274
|
-
| `useNumericSummate<E>()` | 创建一个对数字元素求和的完整收集器 | O(n) | O(1) |
|
|
275
|
-
| `useNumericSummate<E>(mapper)` | 创建一个对映射后的数字值求和的完整收集器 | O(n) | O(1) |
|
|
276
|
-
| `useBigIntSummate<E>()` | 创建一个对数字元素求和的完整收集器 | O(n) | O(1) |
|
|
277
|
-
| `useBigIntSummate<E>(mapper)` | 创建一个对映射后的数字值求和的完整收集器 | O(n) | O(1) |
|
|
278
|
-
| `useNumericAverage<E>()` | 创建一个计算数字平均值的完整收集器 | O(n) | O(1) |
|
|
279
|
-
| `useNumericAverage<E>(mapper)` | 创建一个通过映射器计算数字平均值的完整收集器 | O(n) | O(1) |
|
|
280
|
-
| `useBigIntAverage<E>()` | 创建一个计算 BigInt 平均值的完整收集器 | O(n) | O(1) |
|
|
281
|
-
| `useBigIntAverage<E>(mapper)` | 创建一个通过映射器计算 BigInt 平均值的完整收集器 | O(n) | O(1) |
|
|
282
|
-
| `useFrequency<E>()` | 创建一个统计元素频率的完整收集器 | O(n) | O(n) |
|
|
283
|
-
| `useNumericMode<E>()` | 创建一个计算数字众数的完整收集器 | O(n) | O(n) |
|
|
284
|
-
| `useNumericMode<E>(mapper)` | 创建一个通过映射器计算数字众数的完整收集器 | O(n) | O(n) |
|
|
285
|
-
| `useBigIntMode<E>()` | 创建一个计算 BigInt 众数的完整收集器 | O(n) | O(n) |
|
|
286
|
-
| `useBigIntMode<E>(mapper)` | 创建一个通过映射器计算 BigInt 众数的完整收集器 | O(n) | O(n) |
|
|
287
|
-
| `useNumericVariance<E>()` | 创建一个计算数字方差的完整收集器 | O(n) | O(1) |
|
|
288
|
-
| `useNumericVariance<E>(mapper)` | 创建一个通过映射器计算数字方差的完整收集器 | O(n) | O(1) |
|
|
289
|
-
| `useBigIntVariance<E>()` | 创建一个计算 BigInt 方差的完整收集器 | O(n) | O(1) |
|
|
290
|
-
| `useBigIntVariance<E>(mapper)` | 创建一个通过映射器计算 BigInt 方差的完整收集器 | O(n) | O(1) |
|
|
291
|
-
| `useNumericStandardDeviation<E>()` | 创建一个计算数字标准差的完整收集器 | O(n) | O(1) |
|
|
292
|
-
| `useNumericStandardDeviation<E>(mapper)` | 创建一个通过映射器计算数字标准差的完整收集器 | O(n) | O(1) |
|
|
293
|
-
| `useBigIntStandardDeviation<E>()` | 创建一个计算 BigInt 标准差的完整收集器 | O(n) | O(1) |
|
|
294
|
-
| `useBigIntStandardDeviation<E>(mapper)` | 创建一个通过映射器计算 BigInt 标准差的完整收集器 | O(n) | O(1) |
|
|
295
|
-
| `useNumericMedian<E>()` | 创建一个计算数字中位数的完整收集器 | O(n) | O(1) |
|
|
296
|
-
| `useNumericMedian<E>(mapper)` | 创建一个通过映射器计算数字中位数的完整收集器 | O(n) | O(1) |
|
|
297
|
-
| `useBigIntMedian<E>()` | 创建一个计算 BigInt 中位数的完整收集器 | O(n) | O(1) |
|
|
298
|
-
| `useBigIntMedian<E>(mapper)` | 创建一个通过映射器计算 BigInt 中位数的完整收集器 | O(n) | O(1) |
|
|
299
|
-
| `useToGeneratorFunction<E>()` | 创建一个将流转换为生成器函数的完整收集器 | O(n) | O(1) |
|
|
300
|
-
| `useToAsyncGeneratorFunction<E>()` | 创建一个将流转换为异步生成器函数的完整收集器 | O(n) | O(1) |
|
|
80
|
+
### 2. 转换流(中间操作)
|
|
81
|
+
通过链式惰性调用来定义管道。
|
|
301
82
|
|
|
302
83
|
```typescript
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
//
|
|
307
|
-
|
|
308
|
-
.filter((n: number): boolean => n > 3)
|
|
309
|
-
.toUnoredered();
|
|
310
|
-
|
|
311
|
-
// 需要排序:使用有序收集器
|
|
312
|
-
let ordered: OrderedCollectable<number> = from([3, 1, 4, 1, 5, 9, 2, 6, 5])
|
|
313
|
-
.sorted();
|
|
314
|
-
|
|
315
|
-
// 统计元素数量
|
|
316
|
-
let count: Collector<number, number, number> = useCount();
|
|
317
|
-
count.collect(from([1,2,3,4,5])); // 从流中统计
|
|
318
|
-
count.collect([1,2,3,4,5]); // 从可迭代对象中统计
|
|
319
|
-
|
|
320
|
-
// 查找第一个元素
|
|
321
|
-
let findFirst: Collector<number, number, number> = useFindFirst();
|
|
322
|
-
find.collect(from([1,2,3,4,5])); // 从流中查找第一个元素
|
|
323
|
-
find.collect([1,2,3,4,5]); // 从可迭代对象中查找第一个元素
|
|
324
|
-
|
|
325
|
-
// 计算元素总和
|
|
326
|
-
let summate: Collector<number, number, number> = useSummate();
|
|
327
|
-
summate.collect(from([1,2,3,4,5])); // 从流中求和
|
|
328
|
-
summate.collect([1,2,3,4,5]); // 从可迭代对象中求和
|
|
329
|
-
|
|
330
|
-
// 计算元素平均值
|
|
331
|
-
let average: Collector<number, number, number> = useNumericAverage();
|
|
332
|
-
average.collect(from([1,2,3,4,5])); // 从流中求平均
|
|
333
|
-
average.collect([1,2,3,4,5]); // 从可迭代对象中求平均
|
|
334
|
-
```
|
|
84
|
+
const processedStream = staticStream
|
|
85
|
+
.filter(x => x % 2 === 0) // 仅保留偶数
|
|
86
|
+
.map(x => x * 10) // 乘以 10
|
|
87
|
+
.flatMap(x => [x, x + 1]) // 将每个元素转换为两个
|
|
88
|
+
.distinct(); // 移除重复项
|
|
335
89
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
339
|
-
|------------|------------|------------|------------|
|
|
340
|
-
| `collect(stream)` | 从流中收集元素 | O(n) | O(1) |
|
|
341
|
-
| `collect(iterable)` | 从可迭代对象中收集元素 | O(n) | O(1) |
|
|
342
|
-
| `collect(generator)` | 从生成器中收集元素 | O(n) | O(1) |
|
|
343
|
-
| `collect(semantic)` | 从 semantic 流中收集元素 | O(n) | O(1) |
|
|
344
|
-
| `collect(collectable)` | 从 collectable 流中收集元素 | O(n) | O(1) |
|
|
345
|
-
| `collect(start, endExelusive)` | 从范围中收集元素 | O(n) | O(1) |
|
|
346
|
-
|
|
347
|
-
### Semantic 工厂方法
|
|
348
|
-
|
|
349
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
350
|
-
|------|------|------------|------------|
|
|
351
|
-
| `animationFrame(period: number, delay: number = 0)` | 创建一个定时的动画帧流 | O(1)* | O(1) |
|
|
352
|
-
| `attribute(target)` | 从对象的深层属性创建流 | O(n) | O(1) |
|
|
353
|
-
| `blob(blob, chunkSize)` | 从 Blob 创建流 | O(n) | O(chunkSize) |
|
|
354
|
-
| `empty<E>()` | 创建一个空流 | O(1) | O(1) |
|
|
355
|
-
| `fill<E>(element, count)` | 创建一个填充流 | O(n) | O(1) |
|
|
356
|
-
| `from<E>(iterable)` | 从可迭代对象创建流 | O(1) | O(1) |
|
|
357
|
-
| `interval(period, delay?)` | 创建一个定时间隔流 | O(1)* | O(1) |
|
|
358
|
-
| `iterate<E>(generator)` | 从生成器创建流 | O(1) | O(1) |
|
|
359
|
-
| `promise<E>(promise)` | 从 Promise 创建流 | O(1) | O(1) |
|
|
360
|
-
| `range(start, end, step)` | 创建数值范围流 | O(n) | O(1) |
|
|
361
|
-
| `websocket(websocket)` | 从 WebSocket 创建流 | O(1) | O(1) |
|
|
362
|
-
|
|
363
|
-
```typescript
|
|
364
|
-
// Semantic 工厂方法使用示例
|
|
365
|
-
|
|
366
|
-
// 从定时动画帧创建流
|
|
367
|
-
animationFrame(1000)
|
|
368
|
-
.toUnordered()
|
|
369
|
-
.forEach((frame): void => console.log(frame));
|
|
370
|
-
|
|
371
|
-
// 从 Blob 创建流(分块读取)
|
|
372
|
-
blob(someBlob, 1024n)
|
|
373
|
-
.toUnordered()
|
|
374
|
-
.write(WritableStream)
|
|
375
|
-
.then(callback) // 写入流成功
|
|
376
|
-
.catch(callback); // 写入流失败
|
|
377
|
-
|
|
378
|
-
// 创建一个空流,在与其他流连接之前不会执行
|
|
379
|
-
empty<string>()
|
|
380
|
-
.toUnordered()
|
|
381
|
-
.join(); //[]
|
|
382
|
-
|
|
383
|
-
// 创建一个填充流
|
|
384
|
-
let filledStream = fill("hello", 3); // "hello", "hello", "hello"
|
|
385
|
-
|
|
386
|
-
// 创建一个具有初始 2 秒延迟和 5 秒执行周期的定时流,基于定时器机制实现;可能因系统调度精度限制而出现时间漂移。
|
|
387
|
-
let intervalStream = interval(5000, 2000);
|
|
388
|
-
|
|
389
|
-
// 从可迭代对象创建流
|
|
390
|
-
let numberStream = from([1, 2, 3, 4, 5]);
|
|
391
|
-
let stringStream = from(new Set(["Alex", "Bob"]));
|
|
392
|
-
|
|
393
|
-
// 从已解析的 Promise 创建流
|
|
394
|
-
let promisedStream: Semantic<Array<number>> = promise(Promise.resolve([1, 2, 3, 4, 5]));
|
|
395
|
-
|
|
396
|
-
// 创建范围流
|
|
397
|
-
let rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
398
|
-
|
|
399
|
-
// WebSocket 事件流
|
|
400
|
-
let ws = new WebSocket("ws://localhost:8080");
|
|
401
|
-
websocket(ws)
|
|
402
|
-
.filter((event): boolean => event.type === "message"); // 仅监听消息事件
|
|
403
|
-
.toUnordered() // 通常事件不需要有序
|
|
404
|
-
.forEach((event): void => receive(event)); // 接收消息
|
|
90
|
+
// 此时尚未执行任何操作
|
|
405
91
|
```
|
|
406
92
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
410
|
-
|------|------|------------|------------|
|
|
411
|
-
| `concat(semantic)` | 连接两个流 | O(n) | O(1) |
|
|
412
|
-
| `concat(iterable)` | 从可迭代对象连接 | O(n) | O(1) |
|
|
413
|
-
| `distinct()` | 去重 | O(n) | O(n) |
|
|
414
|
-
| `distinct(comparator)` | 使用比较器去重 | O(n²) | O(n) |
|
|
415
|
-
| `dropWhile(predicate)` | 丢弃满足条件的元素 | O(n) | O(1) |
|
|
416
|
-
| `filter(predicate)` | 过滤元素 | O(n) | O(1) |
|
|
417
|
-
| `flat(mapper)` | 扁平化映射 | O(n × m) | O(1) |
|
|
418
|
-
| `flatMap(mapper)` | 扁平化映射为新类型 | O(n × m) | O(1) |
|
|
419
|
-
| `limit(n)` | 限制元素数量 | O(n) | O(1) |
|
|
420
|
-
| `map(mapper)` | 映射转换 | O(n) | O(1) |
|
|
421
|
-
| `peek(consumer)` | 查看元素 | O(n) | O(1) |
|
|
422
|
-
| `redirect(redirector)` | 重定向索引 | O(n) | O(1) |
|
|
423
|
-
| `reverse()` | 反转流 | O(n) | O(1) |
|
|
424
|
-
| `shuffle()` | 随机洗牌 | O(n) | O(1) |
|
|
425
|
-
| `shuffle(mapper)` | 使用映射器洗牌 | O(n) | O(1) |
|
|
426
|
-
| `skip(n)` | 跳过前 n 个元素 | O(n) | O(1) |
|
|
427
|
-
| `sorted()` | 排序 | O(n log n) | O(n) |
|
|
428
|
-
| `sorted(comparator)` | 使用比较器排序 | O(n log n) | O(n) |
|
|
429
|
-
| `sub(start, end)` | 获取子流 | O(n) | O(1) |
|
|
430
|
-
| `takeWhile(predicate)` | 获取满足条件的元素 | O(n) | O(1) |
|
|
431
|
-
| `translate(offset)` | 平移索引 | O(n) | O(1) |
|
|
432
|
-
| `translate(translator)` | 使用翻译器平移索引 | O(n) | O(1) |
|
|
93
|
+
### 3. 执行流(终端操作)
|
|
94
|
+
要获得结果,必须获取一个 Collectable 并调用终端操作。
|
|
433
95
|
|
|
434
96
|
```typescript
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
//
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
.shuffle() // 打乱顺序
|
|
450
|
-
.takeWhile((n: number): boolean => n < 50) // 取出小于 50 的元素
|
|
451
|
-
.toOrdered() // 转换为有序收集器
|
|
452
|
-
.toArray(); // 转换为数组
|
|
97
|
+
// 获取一个无序收集器以提高性能
|
|
98
|
+
const resultArray = await processedStream.toUnordered().toArray();
|
|
99
|
+
console.log(resultArray); // 例如:[20, 21, 40, 41]
|
|
100
|
+
|
|
101
|
+
// 使用内置收集器
|
|
102
|
+
const sum = await processedStream.toUnordered().collect(useSummate());
|
|
103
|
+
console.log(sum);
|
|
104
|
+
|
|
105
|
+
// 或使用通用的 collect 方法
|
|
106
|
+
const customResult = await processedStream.toOrdered().collect(
|
|
107
|
+
() => new Map<number, number>(),
|
|
108
|
+
(map, element, index) => map.set(index, element),
|
|
109
|
+
map => map
|
|
110
|
+
);
|
|
453
111
|
```
|
|
454
112
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
458
|
-
|------------|------------|------------|------------|
|
|
459
|
-
| `sorted()` | 转换为有序收集器 | O(n log n) | O(n) |
|
|
460
|
-
| `sorted(comparator)` | 使用比较器转换为有序收集器 | O(n log n) | O(n) |
|
|
461
|
-
| `toUnordered()` | 转换为无序收集器 | O(1) | O(1) |
|
|
462
|
-
| `toOrdered()` | 转换为有序收集器 | O(1) | O(1) |
|
|
463
|
-
| `toNumericStatistics()` | 转换为数字统计 | O(n) | O(1) |
|
|
464
|
-
| `toBigintStatistics()` | 转换为 BigInt 统计 | O(n) | O(1) |
|
|
465
|
-
| `toWindow()` | 转换为窗口收集器 | O(1) | O(1) |
|
|
466
|
-
| `toCollectable()` | 转换为 `UnorderdCollectable` | O(n) | O(1) |
|
|
467
|
-
| `toCollectable(mapper)` | 转换为自定义的 collectable | O(n) | O(1) |
|
|
113
|
+
### 4. 关键:处理事件流
|
|
114
|
+
事件流(useDocument, useWindow, useHTMLElement, useWebSocket)本质上是无限的。您必须使用诸如 sub、takeWhile 或 limit 等操作来定义何时停止收集事件并完成流。否则,终端操作将无限期等待。
|
|
468
115
|
|
|
469
116
|
```typescript
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
//
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
.toUnorderd() // 丢弃重定向顺序。此操作将忽略 `redirect`、`reverse`、`shuffle` 和 `translate` 操作
|
|
490
|
-
.toArray(); // [2, 5, 3, 4, 6]
|
|
491
|
-
|
|
492
|
-
// 反转流为数组
|
|
493
|
-
from([6, 4, 3, 5, 2])
|
|
494
|
-
.reverse() // 反转流
|
|
495
|
-
.toOrdered() // 保证反转后的顺序
|
|
496
|
-
.toArray(); // [2, 5, 3, 4, 6]
|
|
497
|
-
|
|
498
|
-
// 覆盖洗牌流到数组
|
|
499
|
-
from([6, 4, 3, 5, 2])
|
|
500
|
-
.shuffle() // 打乱流
|
|
501
|
-
.sorted() // 覆盖洗牌顺序。此操作将覆盖 `redirect`、`reverse`、`shuffle` 和 `translate` 操作
|
|
502
|
-
.toArray(); // [2, 5, 3, 4, 6]
|
|
503
|
-
|
|
504
|
-
// 转换为窗口收集器
|
|
505
|
-
from([6, 4, 3, 5, 2]).toWindow();
|
|
506
|
-
|
|
507
|
-
// 转换为数字统计
|
|
508
|
-
from([6, 4, 3, 5, 2]).toNumericStatistics();
|
|
509
|
-
|
|
510
|
-
// 转换为 BigInt 统计
|
|
511
|
-
from([6n, 4n, 3n, 5n, 2n]).toBigintStatistics();
|
|
512
|
-
|
|
513
|
-
// 定义自定义收集器来收集数据
|
|
514
|
-
let customizedCollector = from([1, 2, 3, 4, 5]).toCollectable((generator: Generator<E>) => new CustomizedCollector(generator));
|
|
117
|
+
import { useDocument } from 'semantic-typescript';
|
|
118
|
+
|
|
119
|
+
// 仅收集前 5 次点击
|
|
120
|
+
const first5Clicks = await useDocument('click')
|
|
121
|
+
.limit(5) // <- 关键:将流限制为 5 个事件
|
|
122
|
+
.toUnordered()
|
|
123
|
+
.toArray();
|
|
124
|
+
|
|
125
|
+
// 收集 10 秒窗口内的点击
|
|
126
|
+
const clicksIn10s = await useDocument('click')
|
|
127
|
+
.takeWhile((_, index, startTime = Date.now()) => Date.now() - startTime < 10000)
|
|
128
|
+
.toUnordered()
|
|
129
|
+
.toArray();
|
|
130
|
+
|
|
131
|
+
// 收集索引 2 到 5 的点击(基于 0)
|
|
132
|
+
const specificClicks = await useDocument('click')
|
|
133
|
+
.sub(2n, 6n) // <- 获取索引为 2, 3, 4, 5 的元素
|
|
134
|
+
.toUnordered()
|
|
135
|
+
.toArray();
|
|
515
136
|
```
|
|
516
137
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
520
|
-
|------|------|------------|------------|
|
|
521
|
-
| `anyMatch(predicate)` | 是否有任何元素匹配谓词 | O(n) | O(1) |
|
|
522
|
-
| `allMatch(predicate)` | 是否所有元素都匹配谓词 | O(n) | O(1) |
|
|
523
|
-
| `collect(collector)` | 使用给定的收集器收集元素 | O(n) | O(1) |
|
|
524
|
-
| `collect(identity, accumulator, finisher)` | 使用 identity、accumulator 和 finisher 收集元素 | O(n) | O(1) |
|
|
525
|
-
| `collect(identity, interruptor, accumulator, finisher)` | 使用 identity、interruptor、accumulator 和 finisher 收集元素 | O(n) | O(1) |
|
|
526
|
-
| `count()` | 统计元素数量 | O(n) | O(1) |
|
|
527
|
-
| `error()` | 使用默认错误格式将元素记录到控制台 | O(n) | O(1) |
|
|
528
|
-
| `error(accumulator)` | 通过自定义累加器错误格式记录元素 | O(n) | O(1) |
|
|
529
|
-
| `error(prefix, accumulator, suffix)` | 使用前缀、自定义累加器和后缀记录元素 | O(n) | O(1) |
|
|
530
|
-
| `isEmpty()` | 检查 collectable 是否为空 | O(n) | O(1) |
|
|
531
|
-
| `findAny()` | 在 collectable 中查找任意元素 | O(n) | O(1) |
|
|
532
|
-
| `findFirst()` | 在 collectable 中查找第一个元素 | O(n) | O(1) |
|
|
533
|
-
| `findLast()` | 在 collectable 中查找最后一个元素 | O(n) | O(1) |
|
|
534
|
-
| `findMaximum()` | 在 collectable 中查找最大元素 | O(n) | O(1) |
|
|
535
|
-
| `findMaximum(comparator)` | 使用比较器在 collectable 中查找最大元素 | O(n) | O(1) |
|
|
536
|
-
| `findMinimum()` | 在 collectable 中查找最小元素 | O(n) | O(1) |
|
|
537
|
-
| `findMinimum(comparator)` | 使用比较器在 collectable 中查找最小元素 | O(n) | O(1) |
|
|
538
|
-
| `forEach(action)` | 使用消费者或二元消费者遍历所有元素 | O(n) | O(1) |
|
|
539
|
-
| `group(classifier)` | 通过分类器函数对元素分组 | O(n) | O(n) |
|
|
540
|
-
| `groupBy(keyExtractor, valueExtractor)` | 通过键和值提取器对元素分组 | O(n) | O(n) |
|
|
541
|
-
| `join()` | 使用默认格式将元素连接成字符串 | O(n) | O(n) |
|
|
542
|
-
| `join(delimiter)` | 使用分隔符将元素连接成字符串 | O(n) | O(n) |
|
|
543
|
-
| `join(prefix, delimiter, suffix)` | 使用前缀、分隔符和后缀连接元素 | O(n) | O(n) |
|
|
544
|
-
| `join(prefix, accumulator, suffix)` | 通过自定义累加器连接元素,并带前缀和后缀 | O(n) | O(n) |
|
|
545
|
-
| `log()` | 使用默认格式将元素记录到控制台 | O(n) | O(1) |
|
|
546
|
-
| `log(accumulator)` | 通过自定义累加器记录元素 | O(n) | O(1) |
|
|
547
|
-
| `log(prefix, accumulator, suffix)` | 使用前缀、自定义累加器和后缀记录元素 | O(n) | O(1) |
|
|
548
|
-
| `nonMatch(predicate)` | 是否有任何元素不匹配谓词 | O(n) | O(1) |
|
|
549
|
-
| `partition(count)` | 将元素分割为指定大小的块 | O(n) | O(n) |
|
|
550
|
-
| `partitionBy(classifier)` | 通过分类器函数对元素分区 | O(n) | O(n) |
|
|
551
|
-
| `reduce(accumulator)` | 使用累加器归约元素(无初始值) | O(n) | O(1) |
|
|
552
|
-
| `reduce(identity, accumulator)` | 使用初始值和累加器归约元素 | O(n) | O(1) |
|
|
553
|
-
| `reduce(identity, accumulator, finisher)` | 使用初始值、累加器和 finisher 归约元素 | O(n) | O(1) |
|
|
554
|
-
| `semantic()` | 将 collectable 转换为语义对象 | O(1) | O(1) |
|
|
555
|
-
| `source()` | 获取 collectable 的源 | O(1) | O(1) |
|
|
556
|
-
| `toArray()` | 将元素转换为数组 | O(n) | O(n) |
|
|
557
|
-
| `toMap(keyExtractor, valueExtractor)` | 通过键和值提取器将元素转换为 Map | O(n) | O(n) |
|
|
558
|
-
| `toSet()` | 将元素转换为 Set | O(n) | O(n) |
|
|
559
|
-
| `write(stream)` | 将元素写入流(默认格式) | O(n) | O(1) |
|
|
560
|
-
| `write(stream, accumulator)` | 通过自定义累加器将元素写入流 | O(n) | O(1) |
|
|
138
|
+
**关键见解**:事件(例如 MouseEvent)及其顺序触发索引(作为大整数)通过 `accept(event, index)` 回调一起在管道中传递。
|
|
561
139
|
|
|
140
|
+
### 5. 利用统计功能
|
|
562
141
|
```typescript
|
|
563
|
-
|
|
564
|
-
let data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
565
|
-
.filter((n: number): boolean => n % 2 === 0)
|
|
566
|
-
.toOrdered();
|
|
567
|
-
|
|
568
|
-
// 匹配检查
|
|
569
|
-
console.log(data.anyMatch((n: number): boolean => n > 5)); // true
|
|
570
|
-
console.log(data.allMatch((n: number): boolean => n < 20)); // true
|
|
571
|
-
|
|
572
|
-
// 查找操作
|
|
573
|
-
data.findFirst().ifPresent((n: number): void => console.log(n)); // 2
|
|
574
|
-
data.findAny().ifPresent((n: number): void => console.log(n)); // 任意元素
|
|
575
|
-
|
|
576
|
-
// 分组操作
|
|
577
|
-
let grouped = data.groupBy(
|
|
578
|
-
(n: number): string => n > 5 ? "large" : "small",
|
|
579
|
-
(n: number): number => n * 2
|
|
580
|
-
);
|
|
581
|
-
// {small: [4, 8], large: [12, 16, 20]}
|
|
142
|
+
const numericStream = useFrom([10, 20, 30, 40, 50]).toNumeric();
|
|
582
143
|
|
|
583
|
-
|
|
584
|
-
|
|
144
|
+
const average = await numericStream.average();
|
|
145
|
+
const median = await numericStream.median();
|
|
146
|
+
const standardDeviation = await numericStream.standardDeviation();
|
|
147
|
+
const skewness = await numericStream.skewness();
|
|
585
148
|
|
|
586
|
-
|
|
587
|
-
data.join(", "); // "[2, 4, 6, 8, 10]"
|
|
149
|
+
console.log(`Average: ${average}, Median: ${median}, StdDev: ${standardDeviation}`);
|
|
588
150
|
```
|
|
589
151
|
|
|
590
|
-
##
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
###
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
| `*` | 异步遍历所有元素 | O(n) | O(1) |
|
|
621
|
-
| `average()` | 计算元素平均值 | O(n) | O(1) |
|
|
622
|
-
| `average(mapper)` | 使用映射器计算元素平均值 | O(n) | O(1) |
|
|
623
|
-
| `range()` | 计算元素范围 | O(n) | O(1) |
|
|
624
|
-
| `range(mapper)` | 使用映射器计算元素范围 | O(n) | O(1) |
|
|
625
|
-
| `variance()` | 计算元素方差 | O(n) | O(1) |
|
|
626
|
-
| `variance(mapper)` | 使用映射器计算元素方差 | O(n) | O(1) |
|
|
627
|
-
| `standardDeviation()` | 计算元素标准差 | O(n) | O(1) |
|
|
628
|
-
| `standardDeviation(mapper)` | 使用映射器计算元素标准差 | O(n) | O(1) |
|
|
629
|
-
| `mean()` | 计算元素均值 | O(n) | O(1) |
|
|
630
|
-
| `mean(mapper)` | 使用映射器计算元素均值 | O(n) | O(1) |
|
|
631
|
-
| `median()` | 计算元素中位数 | O(n) | O(1) |
|
|
632
|
-
| `median(mapper)` | 使用映射器计算元素中位数 | O(n) | O(1) |
|
|
633
|
-
| `mode()` | 计算元素众数 | O(n) | O(1) |
|
|
634
|
-
| `mode(mapper)` | 使用映射器计算元素众数 | O(n) | O(1) |
|
|
635
|
-
| `summate()` | 计算元素总和 | O(n) | O(1) |
|
|
636
|
-
| `summate(mapper)` | 使用映射器计算元素总和 | O(n) | O(1) |
|
|
637
|
-
| `quantile(quantile)` | 计算元素分位数 | O(n) | O(1) |
|
|
638
|
-
| `quantile(quantile, mapper)` | 使用映射器计算元素分位数 | O(n) | O(1) |
|
|
639
|
-
| `interquartileRange()` | 计算元素四分位距 | O(n) | O(1) |
|
|
640
|
-
| `interquartileRange(mapper)` | 使用映射器计算元素四分位距 | O(n) | O(1) |
|
|
641
|
-
| `skewness()` | 计算元素偏度 | O(n) | O(1) |
|
|
642
|
-
| `skewness(mapper)` | 使用映射器计算元素偏度 | O(n) | O(1) |
|
|
643
|
-
| `kurtosis()` | 计算元素峰度 | O(n) | O(1) |
|
|
644
|
-
| `kurtosis(mapper)` | 使用映射器计算元素峰度 | O(n) | O(1) |
|
|
645
|
-
|
|
152
|
+
## 主要特性
|
|
153
|
+
- **双流类型**:完全支持同步语义(用于 Iterable)和异步语义(用于 AsyncIterable 和事件)
|
|
154
|
+
- **丰富的操作集**:过滤器、映射、扁平映射、连接、去重、排序、限制、跳过、查看、反转、打乱
|
|
155
|
+
- **灵活的终端操作**:收集(使用自定义收集器)、toArray、toSet、toMap、forEach、reduce、findFirst、anyMatch、allMatch、count
|
|
156
|
+
- **高级收集器**:用于连接、分组、分区、求和、平均、最大值、最小值的内置收集器
|
|
157
|
+
- **统计模块**:在数值/大整数流上用于均值、中位数、众数、方差、标准差、范围、分位数、偏度、峰度的即用型方法
|
|
158
|
+
- **实用函数**:类型守卫(isPromise, isAsyncIterable)、比较器(useCompare)、遍历(useTraverse)和转换钩子
|
|
159
|
+
- **Optional<T>**:一个用于可空值的单子容器,与查找操作集成
|
|
160
|
+
|
|
161
|
+
## API 概述
|
|
162
|
+
### 核心类和接口
|
|
163
|
+
- `Semantic<E>` / `AsynchronousSemantic<E>`:抽象的流定义
|
|
164
|
+
- `Collectable<E>` / `AsynchronousCollectable<E>`:具有终端操作的可执行流
|
|
165
|
+
- `OrderedCollectable<E>` / `UnorderedCollectable<E>`:为顺序敏感或顺序不敏感操作优化的实例化版本
|
|
166
|
+
- `Collector<E, A, R>`:可变归约操作的抽象
|
|
167
|
+
|
|
168
|
+
### 工厂函数 (use*)
|
|
169
|
+
- **从源创建**:useFrom, useRange, useFill, useEmpty
|
|
170
|
+
- **从时间创建**:useInterval, useAnimationFrame
|
|
171
|
+
- **从 Web API 创建**:useBlob, useDocument, useWindow, useHTMLElement, useWebSocket
|
|
172
|
+
- **收集器**:useToArray, useGroupBy, useSummate, useJoin 等
|
|
173
|
+
|
|
174
|
+
## 性能说明
|
|
175
|
+
- **惰性求值**:在调用终端操作之前,管道仅组合而不执行
|
|
176
|
+
- **短路求值**:诸如限制、任何匹配和查找首个等操作将在结果确定后立即停止处理元素
|
|
177
|
+
- **有序与无序**:
|
|
178
|
+
- 当源元素的顺序对您的结果不重要时(例如,求和、最大值或 toSet),对终端操作使用 `.toUnordered()`。这允许内部优化跳过昂贵的排序步骤
|
|
179
|
+
- 当顺序很重要时(例如,toArray 必须保留顺序),使用 `.toOrdered()`
|
|
180
|
+
|
|
181
|
+
## 入门示例
|
|
646
182
|
```typescript
|
|
647
|
-
|
|
648
|
-
let numbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
649
|
-
.toNumericStatistics();
|
|
650
|
-
|
|
651
|
-
console.log("平均值:", numbers.mean()); // 5.5
|
|
652
|
-
console.log("中位数:", numbers.median()); // 5.5
|
|
653
|
-
console.log("标准差:", numbers.standardDeviation()); // ~2.87
|
|
654
|
-
console.log("总和:", numbers.summate()); // 55
|
|
655
|
-
|
|
656
|
-
// 使用映射器的统计分析
|
|
657
|
-
let objects = from([
|
|
658
|
-
{ value: 10 },
|
|
659
|
-
{ value: 20 },
|
|
660
|
-
{ value: 30 }
|
|
661
|
-
]).toNumericStatistics();
|
|
662
|
-
|
|
663
|
-
console.log("映射后的平均值:", objects.mean(obj => obj.value)); // 20
|
|
664
|
-
```
|
|
183
|
+
import { useFrom, useSummate, useGroupBy } from 'semantic-typescript';
|
|
665
184
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
| `*` | 异步遍历所有元素 | O(n) | O(1) |
|
|
672
|
-
| `average()` | 计算元素平均值 | O(n) | O(1) |
|
|
673
|
-
| `average(mapper)` | 使用映射器计算元素平均值 | O(n) | O(1) |
|
|
674
|
-
| `range()` | 计算元素范围 | O(n) | O(1) |
|
|
675
|
-
| `range(mapper)` | 使用映射器计算元素范围 | O(n) | O(1) |
|
|
676
|
-
| `variance()` | 计算元素方差 | O(n) | O(1) |
|
|
677
|
-
| `variance(mapper)` | 使用映射器计算元素方差 | O(n) | O(1) |
|
|
678
|
-
| `standardDeviation()` | 计算元素标准差 | O(n) | O(1) |
|
|
679
|
-
| `standardDeviation(mapper)` | 使用映射器计算元素标准差 | O(n) | O(1) |
|
|
680
|
-
| `mean()` | 计算元素均值 | O(n) | O(1) |
|
|
681
|
-
| `mean(mapper)` | 使用映射器计算元素均值 | O(n) | O(1) |
|
|
682
|
-
| `median()` | 计算元素中位数 | O(n) | O(1) |
|
|
683
|
-
| `median(mapper)` | 使用映射器计算元素中位数 | O(n) | O(1) |
|
|
684
|
-
| `mode()` | 计算元素众数 | O(n) | O(1) |
|
|
685
|
-
| `mode(mapper)` | 使用映射器计算元素众数 | O(n) | O(1) |
|
|
686
|
-
| `summate()` | 计算元素总和 | O(n) | O(1) |
|
|
687
|
-
| `summate(mapper)` | 使用映射器计算元素总和 | O(n) | O(1) |
|
|
688
|
-
| `quantile(quantile)` | 计算元素分位数 | O(n) | O(1) |
|
|
689
|
-
| `quantile(quantile, mapper)` | 使用映射器计算元素分位数 | O(n) | O(1) |
|
|
690
|
-
| `interquartileRange()` | 计算元素四分位距 | O(n) | O(1) |
|
|
691
|
-
| `interquartileRange(mapper)` | 使用映射器计算元素四分位距 | O(n) | O(1) |
|
|
692
|
-
| `skewness()` | 计算元素偏度 | O(n) | O(1) |
|
|
693
|
-
| `skewness(mapper)` | 使用映射器计算元素偏度 | O(n) | O(1) |
|
|
694
|
-
| `kurtosis()` | 计算元素峰度 | O(n) | O(1) |
|
|
695
|
-
| `kurtosis(mapper)` | 使用映射器计算元素峰度 | O(n) | O(1) |
|
|
696
|
-
|
|
697
|
-
### Window Collectable 方法
|
|
698
|
-
|
|
699
|
-
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|
|
700
|
-
|------------|------------|------------|------------|
|
|
701
|
-
| `*` | 遍历所有元素 | O(n) | O(1) |
|
|
702
|
-
| `*` | 异步遍历所有元素 | O(n) | O(1) |
|
|
703
|
-
| `slide(size)` | 滑动指定大小的窗口 | O(n) | O(1) |
|
|
704
|
-
| `slide(size, step)` | 滑动指定大小和步长的窗口 | O(n) | O(1) |
|
|
705
|
-
| `tumble(size)` | 滚动指定大小的窗口 | O(n) | O(1) |
|
|
706
|
-
|
|
707
|
-
## 性能选择指南
|
|
708
|
-
|
|
709
|
-
### 选择无序收集器(性能优先)
|
|
710
|
-
```typescript
|
|
711
|
-
// 当不需要顺序保证时,使用无序收集器以获得最佳性能
|
|
712
|
-
let highPerformance = data
|
|
713
|
-
.filter(predicate)
|
|
714
|
-
.map(mapper)
|
|
715
|
-
.toUnoredered(); // 最佳性能
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
### 选择有序收集器(需要顺序)
|
|
719
|
-
```typescript
|
|
720
|
-
// 当需要保持元素顺序时,使用有序收集器
|
|
721
|
-
let ordered = data.sorted(comparator);
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
### 选择窗口收集器(窗口操作)
|
|
725
|
-
```typescript
|
|
726
|
-
// 当需要窗口操作时
|
|
727
|
-
let window: WindowCollectable<number> = data
|
|
728
|
-
.toWindow()
|
|
729
|
-
.slide(5n, 2n); // 滑动窗口
|
|
730
|
-
```
|
|
731
|
-
|
|
732
|
-
### 选择统计分析(数值计算)
|
|
733
|
-
```typescript
|
|
734
|
-
// 当需要统计分析时
|
|
735
|
-
let statistics: NumericStatistics<number> = data
|
|
736
|
-
.toNumericStatistics(); // 数字统计
|
|
185
|
+
interface Transaction {
|
|
186
|
+
id: number;
|
|
187
|
+
amount: number;
|
|
188
|
+
category: string;
|
|
189
|
+
}
|
|
737
190
|
|
|
738
|
-
|
|
739
|
-
|
|
191
|
+
const transactions: Transaction[] = [
|
|
192
|
+
{ id: 1, amount: 100, category: 'Food' },
|
|
193
|
+
{ id: 2, amount: 200, category: 'Electronics' },
|
|
194
|
+
{ id: 3, amount: 50, category: 'Food' },
|
|
195
|
+
{ id: 4, amount: 300, category: 'Electronics' },
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
// 计算每个类别的总金额
|
|
199
|
+
const totalsByCategory = await useFrom(transactions)
|
|
200
|
+
.toUnordered()
|
|
201
|
+
.collect(
|
|
202
|
+
useGroupBy(
|
|
203
|
+
t => t.category,
|
|
204
|
+
t => t.amount,
|
|
205
|
+
useSummate() // 值的收集器
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
console.log(totalsByCategory); // Map { 'Food' => 150, 'Electronics' => 500 }
|
|
740
210
|
```
|
|
741
211
|
|
|
742
|
-
|
|
743
|
-
https://www.npmjs.com/package/semantic-typescript
|
|
744
|
-
|
|
745
|
-
## 重要说明
|
|
746
|
-
|
|
747
|
-
1. **排序操作的影响**:在有序收集器中,`sorted()` 操作会覆盖 `redirect`、`translate`、`shuffle`、`reverse` 的效果。
|
|
748
|
-
2. **性能考量**:如果不需要顺序保证,优先使用 `toUnoredered()` 以获得更好的性能。
|
|
749
|
-
3. **内存使用**:排序操作需要 O(n) 的额外空间。
|
|
750
|
-
4. **实时数据**:Semantic 流适用于处理实时数据,并支持异步数据源。
|
|
751
|
-
|
|
212
|
+
Semantic-TypeScript 是为那些寻求严格设计、类型安全和高性能流处理库的开发者而构建的。它将企业级数据转换模式的力量带入了 TypeScript 生态系统,非常适合数据密集型前端应用程序、Node.js 数据处理,以及任何需要优雅、高效处理序列的场景。
|
|
752
213
|
|
|
753
|
-
|
|
214
|
+
[](https://github.com/eloyhere/semantic-typescript) [](https://www.npmjs.com/package/semantic-typescript)
|