semantic-typescript 0.0.7 → 0.0.8
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/package.json +1 -1
- package/readme.cn.md +441 -247
- package/readme.de.md +434 -240
- package/readme.es.md +434 -240
- package/readme.fr.md +434 -240
- package/readme.jp.md +434 -240
- package/readme.kr.md +441 -247
- package/readme.md +434 -240
- package/readme.ru.md +529 -0
- package/readme.tw.md +441 -247
package/readme.tw.md
CHANGED
|
@@ -1,335 +1,529 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Semantic-TypeScript 串流處理框架
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
提供可組合的函數式結構,用於處理集合(Collections)、資料流(Streams)與序列(Sequences),並支援排序、篩選、分組、統計分析等多種功能。
|
|
3
|
+
## 引言
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Semantic-TypeScript 是一個現代化的串流處理函式庫,靈感來自 JavaScript GeneratorFunction、Java Stream 和 MySQL Index。其核心設計理念基於透過資料索引建構高效的資料處理管道,為前端開發提供型別安全、函數式風格的串流操作體驗。
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
與傳統的同步處理不同,Semantic 採用非同步處理模型。在建立資料流時,終端資料接收的時機完全取決於上游何時呼叫 `accept` 和 `interrupt` 回呼函數。這種設計使得函式庫能夠優雅地處理即時資料流、大型資料集和非同步資料來源。
|
|
9
8
|
|
|
10
|
-
##
|
|
9
|
+
## 核心特性
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
- ✅ **函數式編程風格**(例如:map、filter、reduce)
|
|
14
|
-
- ✅ **語意化資料流(Semantic<E>)**,支援延遲求值(Lazy Evaluation)
|
|
15
|
-
- ✅ 可將資料流轉換為實體資料結構的**收集器(Collectors)**
|
|
16
|
-
- ✅ **已排序與未排序的收集器(Collectables)** — 其中 `toUnordered()` 是**最快的(不會排序)**
|
|
17
|
-
- ✅ 支援透過 `sorted()`、`toOrdered()` 與自訂比較器進行**排序**
|
|
18
|
-
- ✅ **統計分析功能**(`Statistics`、`NumericStatistics`、`BigIntStatistics`)
|
|
19
|
-
- ✅ **Optional<T>** — 安全處理可能為 `null` 或 `undefined` 值的 Monad
|
|
20
|
-
- ✅ 採用**迭代器(Iterator)與生成器(Generator)**架構,適用於大型或非同步資料
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 📦 安裝方式
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm install semantic-typescript
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 🧠 核心概念
|
|
33
|
-
|
|
34
|
-
### 1. `Optional<T>` — 安全處理可為空(Nullable)的值
|
|
35
|
-
|
|
36
|
-
用來包裝可能為 `null` 或 `undefined` 的值的 Monad 容器。
|
|
37
|
-
|
|
38
|
-
#### 提供的方法:
|
|
39
|
-
|
|
40
|
-
| 方法 | 說明 | 範例 |
|
|
11
|
+
| 特性 | 描述 | 優勢 |
|
|
41
12
|
|------|------|------|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
13
|
+
| **型別安全泛型** | 完整的 TypeScript 型別支援 | 編譯時錯誤檢測,更好的開發體驗 |
|
|
14
|
+
| **函數式程式設計** | 不可變資料結構和純函數 | 更可預測的程式碼,易於測試和維護 |
|
|
15
|
+
| **惰性求值** | 按需計算,效能最佳化 | 處理大型資料集時記憶體效率高 |
|
|
16
|
+
| **非同步串流處理** | 基於產生器的非同步資料流 | 適用於即時資料和事件驅動場景 |
|
|
17
|
+
| **多範型收集器** | 有序、無序、統計收集策略 | 根據不同場景選擇最佳策略 |
|
|
18
|
+
| **統計分析** | 內建完整的統計計算函數 | 整合資料分析和報表生成 |
|
|
19
|
+
|
|
20
|
+
## 效能考量
|
|
21
|
+
|
|
22
|
+
**重要注意**:以下方法會犧牲效能來收集和排序資料,從而產生有序的資料集合:
|
|
23
|
+
- `toOrdered()`
|
|
24
|
+
- `toWindow()`
|
|
25
|
+
- `toNumericStatistics()`
|
|
26
|
+
- `toBigIntStatistics()`
|
|
27
|
+
- `sorted()`
|
|
28
|
+
- `sorted(comparator)`
|
|
29
|
+
|
|
30
|
+
特別需要注意的是:`sorted()` 和 `sorted(comparator)` 會覆寫以下方法的結果:
|
|
31
|
+
- `redirect(redirector)`
|
|
32
|
+
- `translate(translator)`
|
|
33
|
+
- `shuffle(mapper)`
|
|
34
|
+
|
|
35
|
+
## 工廠方法
|
|
36
|
+
|
|
37
|
+
### 串流建立工廠
|
|
38
|
+
|
|
39
|
+
| 方法 | 簽章 | 描述 | 範例 |
|
|
40
|
+
|------|------|------|------|
|
|
41
|
+
| `blob` | `(blob: Blob, chunk?: bigint) => Semantic<Uint8Array>` | 將 Blob 轉換為位元組流 | `blob(fileBlob, 1024n)` |
|
|
42
|
+
| `empty` | `<E>() => Semantic<E>` | 建立空串流 | `empty<number>()` |
|
|
43
|
+
| `fill` | `<E>(element: E, count: bigint) => Semantic<E>` | 填充指定數量的元素 | `fill("hello", 5n)` |
|
|
44
|
+
| `from` | `<E>(iterable: Iterable<E>) => Semantic<E>` | 從可迭代物件建立串流 | `from([1, 2, 3])` |
|
|
45
|
+
| `range` | `<N extends number\|bigint>(start: N, end: N, step?: N) => Semantic<N>` | 建立數值範圍串流 | `range(1, 10, 2)` |
|
|
46
|
+
| `iterate` | `<E>(generator: Generator<E>) => Semantic<E>` | 從產生器函數建立串流 | `iterate(myGenerator)` |
|
|
47
|
+
| `websocket` | `(websocket: WebSocket) => Semantic<MessageEvent>` | 從 WebSocket 建立事件流 | `websocket(socket)` |
|
|
48
|
+
|
|
49
|
+
**程式碼範例補充:**
|
|
55
50
|
```typescript
|
|
56
|
-
import {
|
|
51
|
+
import { from, range, fill, empty } from 'semantic-typescript';
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
// 從陣列建立串流
|
|
54
|
+
const numberStream = from([1, 2, 3, 4, 5]);
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
// 建立數值範圍串流
|
|
57
|
+
const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
61
58
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.map(v => v * 2)
|
|
65
|
-
.getOrDefault(0);
|
|
59
|
+
// 填充重複元素
|
|
60
|
+
const filledStream = fill("hello", 3n); // "hello", "hello", "hello"
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
// 建立空串流
|
|
63
|
+
const emptyStream = empty<number>();
|
|
68
64
|
```
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
### 2. `Semantic<E>` — 延遲資料流(Lazy Data Stream)
|
|
73
|
-
|
|
74
|
-
一個**可組合、延遲求值的資料序列**,類似於 Java 的 Streams 或 Kotlin 的 Sequences。
|
|
66
|
+
### 實用函數工廠
|
|
75
67
|
|
|
76
|
-
|
|
68
|
+
| 方法 | 簽章 | 描述 | 範例 |
|
|
69
|
+
|------|------|------|------|
|
|
70
|
+
| `validate` | `<T>(t: MaybeInvalid<T>) => t is T` | 驗證值是否有效 | `validate(null)` → `false` |
|
|
71
|
+
| `invalidate` | `<T>(t: MaybeInvalid<T>) => t is null\|undefined` | 驗證值是否無效 | `invalidate(0)` → `false` |
|
|
72
|
+
| `useCompare` | `<T>(t1: T, t2: T) => number` | 通用比較函數 | `useCompare("a", "b")` → `-1` |
|
|
73
|
+
| `useRandom` | `<T = number\|bigint>(index: T) => T` | 偽隨機數產生器 | `useRandom(5)` → 隨機數 |
|
|
77
74
|
|
|
78
|
-
|
|
75
|
+
**程式碼範例補充:**
|
|
76
|
+
```typescript
|
|
77
|
+
import { validate, invalidate, useCompare, useRandom } from 'semantic-typescript';
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
| `iterate(gen)` | 使用自訂的生成器函數 | `iterate(genFn)` |
|
|
79
|
+
// 驗證資料有效性
|
|
80
|
+
const data: string | null = "hello";
|
|
81
|
+
if (validate(data)) {
|
|
82
|
+
console.log(data.toUpperCase()); // 安全呼叫,因為 validate 確保資料不為 null
|
|
83
|
+
}
|
|
86
84
|
|
|
87
|
-
|
|
85
|
+
const nullData: string | null = null;
|
|
86
|
+
if (invalidate(nullData)) {
|
|
87
|
+
console.log("資料無效"); // 會執行,因為 invalidate 檢測到 null
|
|
88
|
+
}
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
| `map(fn)` | 對每個元素進行轉換 | `.map(x => x * 2)` |
|
|
92
|
-
| `filter(fn)` | 僅保留符合條件的元素 | `.filter(x => x > 10)` |
|
|
93
|
-
| `limit(n)` | 限制回傳前 N 個元素 | `.limit(5)` |
|
|
94
|
-
| `skip(n)` | 跳過前 N 個元素 | `.skip(2)` |
|
|
95
|
-
| `distinct()` | 移除重複項(預設使用 Set) | `.distinct()` |
|
|
96
|
-
| `sorted()` | 對元素進行排序(自然順序) | `.sorted()` |
|
|
97
|
-
| `sorted(comparator)` | 使用自訂比較器排序 | `.sorted((a, b) => a - b)` |
|
|
98
|
-
| `toOrdered()` | 排序後回傳 OrderedCollectable | `.toOrdered()` |
|
|
99
|
-
| `toUnordered()` | **不進行排序(最快的方法)** | `.toUnordered()` ✅ |
|
|
100
|
-
| `collect(collector)` | 使用 Collector 進行聚合 | `.collect(Collector.full(...))` |
|
|
101
|
-
| `toArray()` | 轉為陣列 | `.toArray()` |
|
|
102
|
-
| `toSet()` | 轉為 Set | `.toSet()` |
|
|
103
|
-
| `toMap(keyFn, valFn)` | 轉為 Map | `.toMap(x => x.id, x => x)` |
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
### 3. `toUnordered()` — 🚀 最快,不排序
|
|
108
|
-
|
|
109
|
-
如果您**不需要排序**,且希望獲得**最快的效能**,請使用:
|
|
90
|
+
// 比較值
|
|
91
|
+
const comparison = useCompare("apple", "banana"); // -1
|
|
110
92
|
|
|
111
|
-
|
|
112
|
-
const
|
|
93
|
+
// 產生隨機數
|
|
94
|
+
const randomNum = useRandom(42); // 基於種子 42 的隨機數
|
|
113
95
|
```
|
|
114
96
|
|
|
115
|
-
|
|
116
|
-
當資料的順序不重要,而您追求極致效能時,這是最佳選擇。
|
|
97
|
+
## 核心類別詳情
|
|
117
98
|
|
|
118
|
-
|
|
99
|
+
### Optional<T> - 安全空值處理
|
|
119
100
|
|
|
120
|
-
|
|
101
|
+
Optional 類別提供函數式方法來安全處理可能為 null 或 undefined 的值。
|
|
121
102
|
|
|
122
|
-
|
|
103
|
+
| 方法 | 回傳型別 | 描述 | 時間複雜度 |
|
|
104
|
+
|------|----------|------|------------|
|
|
105
|
+
| `filter(predicate: Predicate<T>)` | `Optional<T>` | 過濾滿足條件的值 | O(1) |
|
|
106
|
+
| `get()` | `T` | 獲取值,若為空則拋出錯誤 | O(1) |
|
|
107
|
+
| `getOrDefault(defaultValue: T)` | `T` | 獲取值或預設值 | O(1) |
|
|
108
|
+
| `ifPresent(action: Consumer<T>)` | `void` | 如果值存在則執行動作 | O(1) |
|
|
109
|
+
| `isEmpty()` | `boolean` | 檢查是否為空 | O(1) |
|
|
110
|
+
| `isPresent()` | `boolean` | 檢查值是否存在 | O(1) |
|
|
111
|
+
| `map<R>(mapper: Functional<T, R>)` | `Optional<R>` | 對值進行對映和轉換 | O(1) |
|
|
112
|
+
| `static of<T>(value: MaybeInvalid<T>)` | `Optional<T>` | 建立 Optional 實例 | O(1) |
|
|
113
|
+
| `static ofNullable<T>(value?)` | `Optional<T>` | 建立可為空的 Optional | O(1) |
|
|
114
|
+
| `static ofNonNull<T>(value: T)` | `Optional<T>` | 建立非空 Optional | O(1) |
|
|
123
115
|
|
|
116
|
+
**程式碼範例補充:**
|
|
124
117
|
```typescript
|
|
125
|
-
|
|
126
|
-
const customSorted = semanticStream.sorted((a, b) => a - b); // 自訂比較器
|
|
127
|
-
const orderedCollectable = semanticStream.toOrdered(); // 也會排序
|
|
128
|
-
```
|
|
118
|
+
import { Optional } from 'semantic-typescript';
|
|
129
119
|
|
|
130
|
-
|
|
120
|
+
// 建立 Optional 實例
|
|
121
|
+
const optionalValue = Optional.ofNullable<string>(Math.random() > 0.5 ? "hello" : null);
|
|
131
122
|
|
|
132
|
-
|
|
123
|
+
// 鏈式操作
|
|
124
|
+
const result = optionalValue
|
|
125
|
+
.filter(val => val.length > 3) // 過濾長度大於 3 的值
|
|
126
|
+
.map(val => val.toUpperCase()) // 轉換為大寫
|
|
127
|
+
.getOrDefault("default"); // 獲取值或預設值
|
|
133
128
|
|
|
134
|
-
|
|
129
|
+
console.log(result); // "HELLO" 或 "default"
|
|
135
130
|
|
|
136
|
-
|
|
131
|
+
// 安全操作
|
|
132
|
+
optionalValue.ifPresent(val => {
|
|
133
|
+
console.log(`值存在: ${val}`);
|
|
134
|
+
});
|
|
137
135
|
|
|
138
|
-
|
|
136
|
+
// 檢查狀態
|
|
137
|
+
if (optionalValue.isPresent()) {
|
|
138
|
+
console.log("有值");
|
|
139
|
+
} else if (optionalValue.isEmpty()) {
|
|
140
|
+
console.log("為空");
|
|
141
|
+
}
|
|
142
|
+
```
|
|
139
143
|
|
|
144
|
+
### Semantic<E> - 惰性資料流
|
|
145
|
+
|
|
146
|
+
Semantic 是核心的串流處理類別,提供豐富的串流運算子。
|
|
147
|
+
|
|
148
|
+
#### 串流轉換操作
|
|
149
|
+
|
|
150
|
+
| 方法 | 回傳型別 | 描述 | 效能影響 |
|
|
151
|
+
|------|----------|------|----------|
|
|
152
|
+
| `concat(other: Semantic<E>)` | `Semantic<E>` | 連接兩個串流 | O(n+m) |
|
|
153
|
+
| `distinct()` | `Semantic<E>` | 移除重複項(使用 Set) | O(n) |
|
|
154
|
+
| `distinct(comparator)` | `Semantic<E>` | 自訂比較器去重 | O(n²) |
|
|
155
|
+
| `dropWhile(predicate)` | `Semantic<E>` | 丟棄滿足條件的起始元素 | O(n) |
|
|
156
|
+
| `filter(predicate)` | `Semantic<E>` | 過濾元素 | O(n) |
|
|
157
|
+
| `flat(mapper)` | `Semantic<E>` | 扁平化巢狀串流 | O(n×m) |
|
|
158
|
+
| `flatMap(mapper)` | `Semantic<R>` | 對映並扁平化 | O(n×m) |
|
|
159
|
+
| `limit(n)` | `Semantic<E>` | 限制元素數量 | O(n) |
|
|
160
|
+
| `map(mapper)` | `Semantic<R>` | 對映和轉換元素 | O(n) |
|
|
161
|
+
| `peek(consumer)` | `Semantic<E>` | 檢視元素而不修改 | O(n) |
|
|
162
|
+
| `redirect(redirector)` | `Semantic<E>` | 重新導向索引 | O(n) |
|
|
163
|
+
| `reverse()` | `Semantic<E>` | 反轉串流順序 | O(n) |
|
|
164
|
+
| `shuffle()` | `Semantic<E>` | 隨機洗牌順序 | O(n) |
|
|
165
|
+
| `shuffle(mapper)` | `Semantic<E>` | 自訂洗牌邏輯 | O(n) |
|
|
166
|
+
| `skip(n)` | `Semantic<E>` | 跳過前 n 個元素 | O(n) |
|
|
167
|
+
| `sub(start, end)` | `Semantic<E>` | 獲取子串流 | O(n) |
|
|
168
|
+
| `takeWhile(predicate)` | `Semantic<E>` | 獲取滿足條件的起始元素 | O(n) |
|
|
169
|
+
| `translate(offset)` | `Semantic<E>` | 平移索引 | O(n) |
|
|
170
|
+
| `translate(translator)` | `Semantic<E>` | 自訂索引轉換 | O(n) |
|
|
171
|
+
|
|
172
|
+
**程式碼範例補充:**
|
|
140
173
|
```typescript
|
|
141
|
-
|
|
142
|
-
Collector.shortable(identity, interruptor, accumulator, finisher)
|
|
143
|
-
```
|
|
174
|
+
import { from } from 'semantic-typescript';
|
|
144
175
|
|
|
145
|
-
|
|
176
|
+
const stream = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
146
177
|
|
|
147
|
-
|
|
178
|
+
// 串流轉換操作範例
|
|
179
|
+
const processedStream = stream
|
|
180
|
+
.filter(x => x % 2 === 0) // 過濾偶數
|
|
181
|
+
.map(x => x * 2) // 每個元素乘以 2
|
|
182
|
+
.distinct() // 移除重複項
|
|
183
|
+
.limit(3) // 限制為前 3 個元素
|
|
184
|
+
.peek((val, index) => console.log(`元素 ${val} 在索引 ${index}`)); // 檢視元素
|
|
148
185
|
|
|
149
|
-
|
|
186
|
+
// 注意:串流尚未執行,需要轉換為 Collectable 以進行終端操作
|
|
187
|
+
```
|
|
150
188
|
|
|
151
|
-
|
|
189
|
+
#### 串流終端操作
|
|
152
190
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
191
|
+
| 方法 | 回傳型別 | 描述 | 效能特性 |
|
|
192
|
+
|------|----------|------|----------|
|
|
193
|
+
| `toOrdered()` | `OrderedCollectable<E>` | 轉換為有序集合 | 排序操作,效能較低 |
|
|
194
|
+
| `toUnordered()` | `UnorderedCollectable<E>` | 轉換為無序集合 | 最快,無排序 |
|
|
195
|
+
| `toWindow()` | `WindowCollectable<E>` | 轉換為視窗集合 | 排序操作,效能較低 |
|
|
196
|
+
| `toNumericStatistics()` | `Statistics<E, number>` | 數值統計分析 | 排序操作,效能較低 |
|
|
197
|
+
| `toBigintStatistics()` | `Statistics<E, bigint>` | 大整數統計分析 | 排序操作,效能較低 |
|
|
198
|
+
| `sorted()` | `OrderedCollectable<E>` | 自然排序 | 覆寫重新導向結果 |
|
|
199
|
+
| `sorted(comparator)` | `OrderedCollectable<E>` | 自訂排序 | 覆寫重新導向結果 |
|
|
157
200
|
|
|
158
|
-
|
|
201
|
+
**程式碼範例補充:**
|
|
202
|
+
```typescript
|
|
203
|
+
import { from } from 'semantic-typescript';
|
|
159
204
|
|
|
160
|
-
|
|
161
|
-
|------|------|------|
|
|
162
|
-
| `count()` | 計算元素數量 | `.count()` |
|
|
163
|
-
| `toArray()` | 轉為陣列 | `.toArray()` |
|
|
164
|
-
| `toSet()` | 轉為 Set | `.toSet()` |
|
|
165
|
-
| `toMap(k, v)` | 轉為 Map | `.toMap(x => x.id, x => x)` |
|
|
166
|
-
| `group(k)` | 依鍵值分組 | `.group(x => x.category)` |
|
|
167
|
-
| `findAny()` | 找出任意符合的元素(Optional) | `.findAny()` |
|
|
168
|
-
| `findFirst()` | 找出第一個元素(Optional) | `.findFirst()` |
|
|
169
|
-
| `reduce(...)` | 自訂縮減邏輯 | `.reduce((a,b) => a + b, 0)` |
|
|
205
|
+
const semanticStream = from([5, 2, 8, 1, 9, 3, 7, 4, 6]);
|
|
170
206
|
|
|
171
|
-
|
|
207
|
+
// 轉換為有序集合(效能較低)
|
|
208
|
+
const ordered = semanticStream.toOrdered();
|
|
172
209
|
|
|
173
|
-
|
|
210
|
+
// 轉換為無序集合(最快)
|
|
211
|
+
const unordered = semanticStream.toUnordered();
|
|
174
212
|
|
|
175
|
-
|
|
213
|
+
// 自然排序
|
|
214
|
+
const sortedNatural = semanticStream.sorted();
|
|
176
215
|
|
|
177
|
-
|
|
216
|
+
// 自訂排序
|
|
217
|
+
const sortedCustom = semanticStream.sorted((a, b) => b - a); // 降序排序
|
|
178
218
|
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
const customSorted = new OrderedCollectable(stream, (a, b) => b - a);
|
|
182
|
-
```
|
|
219
|
+
// 轉換為統計物件
|
|
220
|
+
const stats = semanticStream.toNumericStatistics();
|
|
183
221
|
|
|
184
|
-
|
|
222
|
+
// 注意:必須透過 Semantic 實例呼叫上述方法以獲取 Collectable,然後才能使用終端方法
|
|
223
|
+
```
|
|
185
224
|
|
|
186
|
-
|
|
225
|
+
### Collector<E, A, R> - 資料收集器
|
|
187
226
|
|
|
188
|
-
|
|
227
|
+
收集器用於將串流資料聚合為特定結構。
|
|
189
228
|
|
|
190
|
-
|
|
229
|
+
| 方法 | 描述 | 使用場景 |
|
|
230
|
+
|------|------|----------|
|
|
231
|
+
| `collect(generator)` | 執行資料收集 | 串流終端操作 |
|
|
232
|
+
| `static full(identity, accumulator, finisher)` | 建立完整收集器 | 需要完整處理 |
|
|
233
|
+
| `static shortable(identity, interruptor, accumulator, finisher)` | 建立可中斷收集器 | 可能提前終止 |
|
|
191
234
|
|
|
235
|
+
**程式碼範例補充:**
|
|
192
236
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
237
|
+
import { Collector } from 'semantic-typescript';
|
|
238
|
+
|
|
239
|
+
// 建立自訂收集器
|
|
240
|
+
const sumCollector = Collector.full(
|
|
241
|
+
() => 0, // 初始值
|
|
242
|
+
(acc, value) => acc + value, // 累加器
|
|
243
|
+
result => result // 完成函數
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
// 使用收集器(需要先從 Semantic 轉換為 Collectable)
|
|
247
|
+
const numbers = from([1, 2, 3, 4, 5]);
|
|
248
|
+
const sum = numbers.toUnordered().collect(sumCollector); // 15
|
|
196
249
|
```
|
|
197
250
|
|
|
198
|
-
|
|
199
|
-
✅ **當資料順序不重要時,提供最快速的處理方式**
|
|
251
|
+
### Collectable<E> - 可收集資料抽象類別
|
|
200
252
|
|
|
201
|
-
|
|
253
|
+
提供豐富的資料聚合和轉換方法。**注意:必須先透過 Semantic 實例呼叫 sorted()、toOrdered() 等方法獲取 Collectable 實例,然後才能使用以下方法。**
|
|
202
254
|
|
|
203
|
-
|
|
255
|
+
#### 資料查詢操作
|
|
204
256
|
|
|
205
|
-
|
|
257
|
+
| 方法 | 回傳型別 | 描述 | 範例 |
|
|
258
|
+
|------|----------|------|------|
|
|
259
|
+
| `anyMatch(predicate)` | `boolean` | 是否有任何元素匹配 | `anyMatch(x => x > 0)` |
|
|
260
|
+
| `allMatch(predicate)` | `boolean` | 是否所有元素匹配 | `allMatch(x => x > 0)` |
|
|
261
|
+
| `count()` | `bigint` | 元素數量統計 | `count()` → `5n` |
|
|
262
|
+
| `isEmpty()` | `boolean` | 串流是否為空 | `isEmpty()` |
|
|
263
|
+
| `findAny()` | `Optional<E>` | 尋找任意元素 | `findAny()` |
|
|
264
|
+
| `findFirst()` | `Optional<E>` | 尋找第一個元素 | `findFirst()` |
|
|
265
|
+
| `findLast()` | `Optional<E>` | 尋找最後一個元素 | `findLast()` |
|
|
206
266
|
|
|
207
|
-
|
|
267
|
+
**程式碼範例補充:**
|
|
268
|
+
```typescript
|
|
269
|
+
import { from } from 'semantic-typescript';
|
|
208
270
|
|
|
209
|
-
|
|
210
|
-
- `BigIntStatistics<E>` — 適用於 `bigint` 類型
|
|
271
|
+
const numbers = from([1, 2, 3, 4, 5]);
|
|
211
272
|
|
|
212
|
-
|
|
273
|
+
// 必須先轉換為 Collectable 才能使用終端方法
|
|
274
|
+
const collectable = numbers.toUnordered();
|
|
213
275
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
| `variance()` | 變異數 | `.variance()` |
|
|
223
|
-
| `standardDeviation()` | 標準差 | `.standardDeviation()` |
|
|
224
|
-
| `summate()` | 總和 | `.summate()` |
|
|
225
|
-
| `quantile(q)` | 第 q 百分位數(0–1) | `.quantile(0.5)` → 中位數 |
|
|
226
|
-
| `frequency()` | 頻率統計(Map) | `.frequency()` |
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## 🧪 完整範例
|
|
276
|
+
// 資料查詢操作
|
|
277
|
+
const hasEven = collectable.anyMatch(x => x % 2 === 0); // true
|
|
278
|
+
const allPositive = collectable.allMatch(x => x > 0); // true
|
|
279
|
+
const count = collectable.count(); // 5n
|
|
280
|
+
const isEmpty = collectable.isEmpty(); // false
|
|
281
|
+
const firstElement = collectable.findFirst(); // Optional.of(1)
|
|
282
|
+
const anyElement = collectable.findAny(); // 任意元素
|
|
283
|
+
```
|
|
231
284
|
|
|
285
|
+
#### 資料聚合操作
|
|
286
|
+
|
|
287
|
+
| 方法 | 回傳型別 | 描述 | 複雜度 |
|
|
288
|
+
|------|----------|------|--------|
|
|
289
|
+
| `group(classifier)` | `Map<K, E[]>` | 按分類器分組 | O(n) |
|
|
290
|
+
| `groupBy(keyExtractor, valueExtractor)` | `Map<K, V[]>` | 按鍵值提取器分組 | O(n) |
|
|
291
|
+
| `join()` | `string` | 連接為字串 | O(n) |
|
|
292
|
+
| `join(delimiter)` | `string` | 使用分隔符連接 | O(n) |
|
|
293
|
+
| `partition(count)` | `E[][]` | 按數量分割 | O(n) |
|
|
294
|
+
| `partitionBy(classifier)` | `E[][]` | 按分類器分割 | O(n) |
|
|
295
|
+
| `reduce(accumulator)` | `Optional<E>` | 歸約操作 | O(n) |
|
|
296
|
+
| `reduce(identity, accumulator)` | `E` | 帶初始值的歸約 | O(n) |
|
|
297
|
+
| `toArray()` | `E[]` | 轉換為陣列 | O(n) |
|
|
298
|
+
| `toMap(keyExtractor, valueExtractor)` | `Map<K, V>` | 轉換為 Map | O(n) |
|
|
299
|
+
| `toSet()` | `Set<E>` | 轉換為 Set | O(n) |
|
|
300
|
+
|
|
301
|
+
**程式碼範例補充:**
|
|
232
302
|
```typescript
|
|
233
|
-
import { from
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
303
|
+
import { from } from 'semantic-typescript';
|
|
304
|
+
|
|
305
|
+
const people = from([
|
|
306
|
+
{ name: "Alice", age: 25, city: "New York" },
|
|
307
|
+
{ name: "Bob", age: 30, city: "London" },
|
|
308
|
+
{ name: "Charlie", age: 25, city: "New York" }
|
|
309
|
+
]);
|
|
310
|
+
|
|
311
|
+
// 必須先轉換為 Collectable 才能使用聚合操作
|
|
312
|
+
const collectable = people.toUnordered();
|
|
313
|
+
|
|
314
|
+
// 分組操作
|
|
315
|
+
const byCity = collectable.group(person => person.city);
|
|
316
|
+
// Map { "New York" => [{name: "Alice", ...}, {name: "Charlie", ...}], "London" => [{name: "Bob", ...}] }
|
|
317
|
+
|
|
318
|
+
const byAge = collectable.groupBy(
|
|
319
|
+
person => person.age,
|
|
320
|
+
person => person.name
|
|
321
|
+
);
|
|
322
|
+
// Map { 25 => ["Alice", "Charlie"], 30 => ["Bob"] }
|
|
323
|
+
|
|
324
|
+
// 轉換為集合
|
|
325
|
+
const array = collectable.toArray(); // 原始陣列
|
|
326
|
+
const set = collectable.toSet(); // Set 集合
|
|
327
|
+
const map = collectable.toMap(
|
|
328
|
+
person => person.name,
|
|
329
|
+
person => person.age
|
|
330
|
+
); // Map { "Alice" => 25, "Bob" => 30, "Charlie" => 25 }
|
|
331
|
+
|
|
332
|
+
// 歸約操作
|
|
333
|
+
const totalAge = collectable.reduce(0, (acc, person) => acc + person.age); // 80
|
|
334
|
+
const oldest = collectable.reduce((a, b) => a.age > b.age ? a : b); // Optional.of({name: "Bob", age: 30, ...})
|
|
253
335
|
```
|
|
254
336
|
|
|
255
|
-
|
|
337
|
+
### 特定收集器實作
|
|
256
338
|
|
|
257
|
-
|
|
339
|
+
#### UnorderedCollectable<E>
|
|
340
|
+
- **特性**:最快的收集器,無排序
|
|
341
|
+
- **使用場景**:順序不重要,需要最高效能
|
|
342
|
+
- **方法**:繼承所有 Collectable 方法
|
|
258
343
|
|
|
259
|
-
|
|
344
|
+
#### OrderedCollectable<E>
|
|
345
|
+
- **特性**:保證元素順序,效能較低
|
|
346
|
+
- **使用場景**:需要排序結果
|
|
347
|
+
- **特殊方法**:繼承所有方法,維持內部排序狀態
|
|
260
348
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
| `useCompare(a, b)` | 通用比較函數 |
|
|
268
|
-
| `useRandom(x)` | 偽隨機數生成器(趣味用途) |
|
|
349
|
+
#### WindowCollectable<E>
|
|
350
|
+
- **特性**:支援滑動視窗操作
|
|
351
|
+
- **使用場景**:時間序列資料分析
|
|
352
|
+
- **特殊方法**:
|
|
353
|
+
- `slide(size, step)` - 滑動視窗
|
|
354
|
+
- `tumble(size)` - 翻滾視窗
|
|
269
355
|
|
|
270
|
-
|
|
356
|
+
**程式碼範例補充:**
|
|
357
|
+
```typescript
|
|
358
|
+
import { from } from 'semantic-typescript';
|
|
271
359
|
|
|
272
|
-
|
|
360
|
+
const data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
273
361
|
|
|
274
|
-
|
|
362
|
+
// 無序收集器(最快)
|
|
363
|
+
const unordered = data.toUnordered();
|
|
364
|
+
const unorderedArray = unordered.toArray(); // 可能維持原始順序 [1, 2, 3, ...]
|
|
275
365
|
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
accept(i, BigInt(i));
|
|
280
|
-
if (i === 5) interrupt(i);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
const s = new Semantic(gen);
|
|
285
|
-
```
|
|
366
|
+
// 有序收集器
|
|
367
|
+
const ordered = data.toOrdered();
|
|
368
|
+
const orderedArray = ordered.toArray(); // 保證排序 [1, 2, 3, ...]
|
|
286
369
|
|
|
287
|
-
|
|
370
|
+
// 視窗收集器
|
|
371
|
+
const windowed = data.toWindow();
|
|
372
|
+
const slidingWindows = windowed.slide(3n, 2n); // 視窗大小 3,步長 2
|
|
373
|
+
// 視窗 1: [1, 2, 3], 視窗 2: [3, 4, 5], 視窗 3: [5, 6, 7], ...
|
|
288
374
|
|
|
289
|
-
|
|
290
|
-
|
|
375
|
+
const tumblingWindows = windowed.tumble(4n); // 翻滾視窗大小 4
|
|
376
|
+
// 視窗 1: [1, 2, 3, 4], 視窗 2: [5, 6, 7, 8], ...
|
|
291
377
|
```
|
|
292
378
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
379
|
+
### Statistics<E, D> - 統計分析
|
|
380
|
+
|
|
381
|
+
統計分析基礎類別,提供豐富的統計計算方法。**注意:必須先透過 Semantic 實例呼叫 toNumericStatistics() 或 toBigIntStatistics() 獲取 Statistics 實例,然後才能使用以下方法。**
|
|
382
|
+
|
|
383
|
+
#### 統計計算操作
|
|
384
|
+
|
|
385
|
+
| 方法 | 回傳型別 | 描述 | 演算法複雜度 |
|
|
386
|
+
|------|----------|------|------------|
|
|
387
|
+
| `maximum()` | `Optional<E>` | 最大值 | O(n) |
|
|
388
|
+
| `minimum()` | `Optional<E>` | 最小值 | O(n) |
|
|
389
|
+
| `range()` | `D` | 範圍(最大值-最小值) | O(n) |
|
|
390
|
+
| `variance()` | `D` | 變異數 | O(n) |
|
|
391
|
+
| `standardDeviation()` | `D` | 標準差 | O(n) |
|
|
392
|
+
| `mean()` | `D` | 平均值 | O(n) |
|
|
393
|
+
| `median()` | `D` | 中位數 | O(n log n) |
|
|
394
|
+
| `mode()` | `D` | 眾數 | O(n) |
|
|
395
|
+
| `frequency()` | `Map<D, bigint>` | 頻率分佈 | O(n) |
|
|
396
|
+
| `summate()` | `D` | 總和 | O(n) |
|
|
397
|
+
| `quantile(quantile)` | `D` | 分位數 | O(n log n) |
|
|
398
|
+
| `interquartileRange()` | `D` | 四分位距 | O(n log n) |
|
|
399
|
+
| `skewness()` | `D` | 偏度 | O(n) |
|
|
400
|
+
| `kurtosis()` | `D` | 峰度 | O(n) |
|
|
401
|
+
|
|
402
|
+
**程式碼範例補充:**
|
|
403
|
+
```typescript
|
|
404
|
+
import { from } from 'semantic-typescript';
|
|
405
|
+
|
|
406
|
+
const numbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
407
|
+
|
|
408
|
+
// 必須先轉換為統計物件才能使用統計方法
|
|
409
|
+
const stats = numbers.toNumericStatistics();
|
|
410
|
+
|
|
411
|
+
// 基礎統計
|
|
412
|
+
const count = stats.count(); // 10n
|
|
413
|
+
const max = stats.maximum(); // Optional.of(10)
|
|
414
|
+
const min = stats.minimum(); // Optional.of(1)
|
|
415
|
+
const range = stats.range(); // 9
|
|
416
|
+
const mean = stats.mean(); // 5.5
|
|
417
|
+
const median = stats.median(); // 5.5
|
|
418
|
+
const sum = stats.summate(); // 55
|
|
419
|
+
|
|
420
|
+
// 進階統計
|
|
421
|
+
const variance = stats.variance(); // 8.25
|
|
422
|
+
const stdDev = stats.standardDeviation(); // 2.872
|
|
423
|
+
const mode = stats.mode(); // 任意值(因為每個都出現一次)
|
|
424
|
+
const q1 = stats.quantile(0.25); // 3.25
|
|
425
|
+
const q3 = stats.quantile(0.75); // 7.75
|
|
426
|
+
const iqr = stats.interquartileRange(); // 4.5
|
|
427
|
+
|
|
428
|
+
// 頻率分佈
|
|
429
|
+
const freq = stats.frequency(); // Map {1 => 1n, 2 => 1n, ...}
|
|
430
|
+
```
|
|
298
431
|
|
|
299
|
-
|
|
432
|
+
#### 特定統計實作類別
|
|
300
433
|
|
|
301
|
-
|
|
434
|
+
**NumericStatistics<E>**
|
|
435
|
+
- 處理 number 型別的統計分析
|
|
436
|
+
- 所有統計計算回傳 number 型別
|
|
302
437
|
|
|
303
|
-
|
|
438
|
+
**BigIntStatistics<E>**
|
|
439
|
+
- 處理 bigint 型別的統計分析
|
|
440
|
+
- 所有統計計算回傳 bigint 型別
|
|
304
441
|
|
|
305
|
-
|
|
442
|
+
**程式碼範例補充:**
|
|
443
|
+
```typescript
|
|
444
|
+
import { from } from 'semantic-typescript';
|
|
306
445
|
|
|
307
|
-
|
|
446
|
+
// 數值統計
|
|
447
|
+
const numberData = from([10, 20, 30, 40, 50]);
|
|
448
|
+
const numericStats = numberData.toNumericStatistics();
|
|
308
449
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
| 安全處理 null/undefined | `Optional<T>` |
|
|
312
|
-
| 建立資料流 | `from([...])`、`range()`、`fill()` |
|
|
313
|
-
| 資料轉換 | `map()`、`filter()` |
|
|
314
|
-
| 資料排序 | `sorted()`、`toOrdered()` |
|
|
315
|
-
| 不排序(最快) | `toUnordered()` ✅ |
|
|
316
|
-
| 分組 / 聚合 | `toMap()`、`group()`、`Collector` |
|
|
317
|
-
| 統計分析 | `NumericStatistics`、`mean()`、`median()` 等 |
|
|
450
|
+
console.log(numericStats.mean()); // 30
|
|
451
|
+
console.log(numericStats.summate()); // 150
|
|
318
452
|
|
|
319
|
-
|
|
453
|
+
// 大整數統計
|
|
454
|
+
const bigintData = from([100n, 200n, 300n, 400n, 500n]);
|
|
455
|
+
const bigintStats = bigintData.toBigIntStatistics();
|
|
320
456
|
|
|
321
|
-
|
|
457
|
+
console.log(bigintStats.mean()); // 300n
|
|
458
|
+
console.log(bigintStats.summate()); // 1500n
|
|
322
459
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
460
|
+
// 使用對映函數的統計
|
|
461
|
+
const objectData = from([
|
|
462
|
+
{ value: 15 },
|
|
463
|
+
{ value: 25 },
|
|
464
|
+
{ value: 35 },
|
|
465
|
+
{ value: 45 }
|
|
466
|
+
]);
|
|
326
467
|
|
|
327
|
-
|
|
468
|
+
const objectStats = objectData.toNumericStatistics();
|
|
469
|
+
const meanWithMapper = objectStats.mean(obj => obj.value); // 30
|
|
470
|
+
const sumWithMapper = objectStats.summate(obj => obj.value); // 120
|
|
471
|
+
```
|
|
328
472
|
|
|
329
|
-
|
|
473
|
+
## 完整使用範例
|
|
330
474
|
|
|
331
|
-
|
|
475
|
+
```typescript
|
|
476
|
+
import { from, validate, invalidate } from 'semantic-typescript';
|
|
477
|
+
|
|
478
|
+
// 1. 建立資料流
|
|
479
|
+
const rawData = [5, 2, 8, 1, null, 9, 3, undefined, 7, 4, 6];
|
|
480
|
+
const semanticStream = from(rawData);
|
|
481
|
+
|
|
482
|
+
// 2. 串流處理管道
|
|
483
|
+
const processedStream = semanticStream
|
|
484
|
+
.filter(val => validate(val)) // 過濾掉 null 和 undefined
|
|
485
|
+
.map(val => val! * 2) // 每個值乘以 2(使用 ! 因為 validate 確保不為空)
|
|
486
|
+
.distinct(); // 移除重複項
|
|
487
|
+
|
|
488
|
+
// 3. 轉換為 Collectable 並使用終端操作
|
|
489
|
+
const collectable = processedStream.toUnordered();
|
|
490
|
+
|
|
491
|
+
// 4. 資料驗證和使用
|
|
492
|
+
if (!collectable.isEmpty()) {
|
|
493
|
+
const results = collectable
|
|
494
|
+
.filter(x => x > 5) // 再次過濾
|
|
495
|
+
.toArray(); // 轉換為陣列
|
|
496
|
+
|
|
497
|
+
console.log("處理結果:", results); // [16, 18, 14, 8, 12]
|
|
498
|
+
|
|
499
|
+
// 統計資訊
|
|
500
|
+
const stats = processedStream.toNumericStatistics();
|
|
501
|
+
console.log("平均值:", stats.mean()); // 11.2
|
|
502
|
+
console.log("總和:", stats.summate()); // 56
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// 5. 處理潛在的無效資料
|
|
506
|
+
const potentiallyInvalidData: Array<number | null> = [1, null, 3, 4, null];
|
|
507
|
+
const validData = potentiallyInvalidData.filter(validate);
|
|
508
|
+
const invalidData = potentiallyInvalidData.filter(invalidate);
|
|
509
|
+
|
|
510
|
+
console.log("有效資料:", validData); // [1, 3, 4]
|
|
511
|
+
console.log("無效資料:", invalidData); // [null, null]
|
|
512
|
+
```
|
|
332
513
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
514
|
+
## 重要使用規則總結
|
|
515
|
+
|
|
516
|
+
1. **建立串流**:使用 `from()`、`range()`、`fill()` 等工廠方法建立 Semantic 實例
|
|
517
|
+
2. **串流轉換**:在 Semantic 實例上呼叫 `map()`、`filter()`、`distinct()` 等方法
|
|
518
|
+
3. **轉換為 Collectable**:必須透過 Semantic 實例呼叫以下方法之一:
|
|
519
|
+
- `toOrdered()` - 有序收集器
|
|
520
|
+
- `toUnordered()` - 無序收集器(最快)
|
|
521
|
+
- `toWindow()` - 視窗收集器
|
|
522
|
+
- `toNumericStatistics()` - 數值統計
|
|
523
|
+
- `toBigIntStatistics()` - 大整數統計
|
|
524
|
+
- `sorted()` - 自然排序
|
|
525
|
+
- `sorted(comparator)` - 自訂排序
|
|
526
|
+
4. **終端操作**:在 Collectable 實例上呼叫 `toArray()`、`count()`、`summate()` 等終端方法
|
|
527
|
+
5. **資料驗證**:使用 `validate()` 確保資料不為 null/undefined,使用 `invalidate()` 檢查無效資料
|
|
528
|
+
|
|
529
|
+
這種設計確保了型別安全性和效能最佳化,同時提供豐富的串流處理功能。
|