semantic-typescript 0.0.7 → 0.1.4
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/semantic.d.ts +22 -5
- package/dist/semantic.js +106 -52
- package/package.json +53 -8
- package/readme.cn.md +360 -269
- package/readme.de.md +356 -264
- package/readme.es.md +357 -264
- package/readme.fr.md +357 -264
- package/readme.jp.md +362 -270
- package/readme.kr.md +361 -269
- package/readme.md +361 -270
- package/readme.ru.md +428 -0
- package/readme.tw.md +354 -263
package/readme.tw.md
CHANGED
|
@@ -1,335 +1,426 @@
|
|
|
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
|
-
##
|
|
11
|
-
|
|
12
|
-
- ✅ 全面採用**類型安全的泛型(Generics)**
|
|
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
|
-
## 📦 安裝方式
|
|
9
|
+
## 安裝
|
|
25
10
|
|
|
26
11
|
```bash
|
|
27
12
|
npm install semantic-typescript
|
|
28
13
|
```
|
|
29
14
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## 🧠 核心概念
|
|
33
|
-
|
|
34
|
-
### 1. `Optional<T>` — 安全處理可為空(Nullable)的值
|
|
35
|
-
|
|
36
|
-
用來包裝可能為 `null` 或 `undefined` 的值的 Monad 容器。
|
|
37
|
-
|
|
38
|
-
#### 提供的方法:
|
|
39
|
-
|
|
40
|
-
| 方法 | 說明 | 範例 |
|
|
41
|
-
|------|------|------|
|
|
42
|
-
| `of(value)` | 包裝一個值(可為空) | `Optional.of(null)` |
|
|
43
|
-
| `ofNullable(v)` | 包裝,允許為空值 | `Optional.ofNullable(someVar)` |
|
|
44
|
-
| `ofNonNull(v)` | 包裝,若為 null/undefined 則拋出例外 | `Optional.ofNonNull(5)` |
|
|
45
|
-
| `get()` | 取得值(若為空則拋出例外) | `opt.get()` |
|
|
46
|
-
| `getOrDefault(d)` | 取得值,若無則回傳預設值 | `opt.getOrDefault(0)` |
|
|
47
|
-
| `ifPresent(fn)` | 若有值則執行副作用 | `opt.ifPresent(x => console.log(x))` |
|
|
48
|
-
| `map(fn)` | 若有值則對其進行轉換 | `opt.map(x => x + 1)` |
|
|
49
|
-
| `filter(fn)` | 僅保留符合條件的值 | `opt.filter(x => x > 0)` |
|
|
50
|
-
| `isEmpty()` | 判斷是否為空 | `opt.isEmpty()` |
|
|
51
|
-
| `isPresent()` | 判斷是否有值 | `opt.isPresent()` |
|
|
15
|
+
## 基礎類型
|
|
52
16
|
|
|
53
|
-
|
|
17
|
+
| 類型 | 描述 |
|
|
18
|
+
|------|------|
|
|
19
|
+
| `Invalid<T>` | 擴展 null 或 undefined 的類型 |
|
|
20
|
+
| `Valid<T>` | 排除 null 和 undefined 的類型 |
|
|
21
|
+
| `MaybeInvalid<T>` | 可能為 null 或 undefined 的類型 |
|
|
22
|
+
| `Primitive` | 原始類型集合 |
|
|
23
|
+
| `MaybePrimitive<T>` | 可能為原始類型的類型 |
|
|
24
|
+
| `OptionalSymbol` | Optional 類的符號標識 |
|
|
25
|
+
| `SemanticSymbol` | Semantic 類的符號標識 |
|
|
26
|
+
| `CollectorsSymbol` | Collector 類的符號標識 |
|
|
27
|
+
| `CollectableSymbol` | Collectable 類的符號標識 |
|
|
28
|
+
| `OrderedCollectableSymbol` | OrderedCollectable 類的符號標識 |
|
|
29
|
+
| `WindowCollectableSymbol` | WindowCollectable 類的符號標識 |
|
|
30
|
+
| `StatisticsSymbol` | Statistics 類的符號標識 |
|
|
31
|
+
| `NumericStatisticsSymbol` | NumericStatistics 類的符號標識 |
|
|
32
|
+
| `BigIntStatisticsSymbol` | BigIntStatistics 類的符號標識 |
|
|
33
|
+
| `UnorderedCollectableSymbol` | UnorderedCollectable 類的符號標識 |
|
|
34
|
+
| `Runnable` | 無參數無返回值的函數 |
|
|
35
|
+
| `Supplier<R>` | 無參數返回 R 的函數 |
|
|
36
|
+
| `Functional<T, R>` | 單參數轉換函數 |
|
|
37
|
+
| `Predicate<T>` | 單參數判斷函數 |
|
|
38
|
+
| `BiFunctional<T, U, R>` | 雙參數轉換函數 |
|
|
39
|
+
| `BiPredicate<T, U>` | 雙參數判斷函數 |
|
|
40
|
+
| `Comparator<T>` | 比較函數 |
|
|
41
|
+
| `TriFunctional<T, U, V, R>` | 三參數轉換函數 |
|
|
42
|
+
| `Consumer<T>` | 單參數消費函數 |
|
|
43
|
+
| `BiConsumer<T, U>` | 雙參數消費函數 |
|
|
44
|
+
| `TriConsumer<T, U, V>` | 三參數消費函數 |
|
|
45
|
+
| `Generator<T>` | 生成器函數 |
|
|
54
46
|
|
|
55
47
|
```typescript
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
const opt = Optional.ofNullable(value);
|
|
61
|
-
|
|
62
|
-
const result = opt
|
|
63
|
-
.filter(v => v > 5)
|
|
64
|
-
.map(v => v * 2)
|
|
65
|
-
.getOrDefault(0);
|
|
66
|
-
|
|
67
|
-
console.log(result); // 20 或 0
|
|
48
|
+
// 類型使用示例
|
|
49
|
+
const predicate: Predicate<number> = (n) => n > 0;
|
|
50
|
+
const mapper: Functional<string, number> = (str) => str.length;
|
|
51
|
+
const comparator: Comparator<number> = (a, b) => a - b;
|
|
68
52
|
```
|
|
69
53
|
|
|
70
|
-
|
|
54
|
+
## 類型守衛
|
|
55
|
+
|
|
56
|
+
| 函數 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
57
|
+
|------|------|------------|------------|
|
|
58
|
+
| `validate<T>(t: MaybeInvalid<T>): t is T` | 驗證值不為 null 或 undefined | O(1) | O(1) |
|
|
59
|
+
| `invalidate<T>(t: MaybeInvalid<T>): t is null \| undefined` | 驗證值為 null 或 undefined | O(1) | O(1) |
|
|
60
|
+
| `isBoolean(t: unknown): t is boolean` | 檢查是否為布林值 | O(1) | O(1) |
|
|
61
|
+
| `isString(t: unknown): t is string` | 檢查是否為字串 | O(1) | O(1) |
|
|
62
|
+
| `isNumber(t: unknown): t is number` | 檢查是否為數字 | O(1) | O(1) |
|
|
63
|
+
| `isFunction(t: unknown): t is Function` | 檢查是否為函數 | O(1) | O(1) |
|
|
64
|
+
| `isObject(t: unknown): t is object` | 檢查是否為物件 | O(1) | O(1) |
|
|
65
|
+
| `isSymbol(t: unknown): t is symbol` | 檢查是否為 Symbol | O(1) | O(1) |
|
|
66
|
+
| `isBigint(t: unknown): t is bigint` | 檢查是否為 BigInt | O(1) | O(1) |
|
|
67
|
+
| `isPrimitive(t: unknown): t is Primitive` | 檢查是否為原始類型 | O(1) | O(1) |
|
|
68
|
+
| `isIterable(t: unknown): t is Iterable<unknown>` | 檢查是否為可迭代物件 | O(1) | O(1) |
|
|
69
|
+
| `isOptional(t: unknown): t is Optional<unknown>` | 檢查是否為 Optional 實例 | O(1) | O(1) |
|
|
70
|
+
| `isSemantic(t: unknown): t is Semantic<unknown>` | 檢查是否為 Semantic 實例 | O(1) | O(1) |
|
|
71
|
+
| `isCollector(t: unknown): t is Collector<unknown, unknown, unknown>` | 檢查是否為 Collector 實例 | O(1) | O(1) |
|
|
72
|
+
| `isCollectable(t: unknown): t is Collectable<unknown>` | 檢查是否為 Collectable 實例 | O(1) | O(1) |
|
|
73
|
+
| `isOrderedCollectable(t: unknown): t is OrderedCollectable<unknown>` | 檢查是否為 OrderedCollectable 實例 | O(1) | O(1) |
|
|
74
|
+
| `isWindowCollectable(t: unknown): t is WindowCollectable<unknown>` | 檢查是否為 WindowCollectable 實例 | O(1) | O(1) |
|
|
75
|
+
| `isUnorderedCollectable(t: unknown): t is UnorderedCollectable<unknown>` | 檢查是否為 UnorderedCollectable 實例 | O(1) | O(1) |
|
|
76
|
+
| `isStatistics(t: unknown): t is Statistics<unknown, number \| bigint>` | 檢查是否為 Statistics 實例 | O(1) | O(1) |
|
|
77
|
+
| `isNumericStatistics(t: unknown): t is NumericStatistics<unknown>` | 檢查是否為 NumericStatistics 實例 | O(1) | O(1) |
|
|
78
|
+
| `isBigIntStatistics(t: unknown): t is BigIntStatistics<unknown>` | 檢查是否為 BigIntStatistics 實例 | O(1) | O(1) |
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
```typescript
|
|
81
|
+
// 類型守衛使用示例
|
|
82
|
+
const value: unknown = "hello";
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
if (isString(value)) {
|
|
85
|
+
console.log(value.length); // 類型安全,value 被推斷為 string
|
|
86
|
+
}
|
|
75
87
|
|
|
76
|
-
|
|
88
|
+
if (isOptional(someValue)) {
|
|
89
|
+
someValue.ifPresent(val => console.log(val));
|
|
90
|
+
}
|
|
91
|
+
```
|
|
77
92
|
|
|
78
|
-
|
|
93
|
+
## 工具函數
|
|
79
94
|
|
|
80
|
-
| 函數 |
|
|
81
|
-
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `fill(element, count)` | 重複某個元素 N 次 | `fill('a', 3n)` |
|
|
85
|
-
| `iterate(gen)` | 使用自訂的生成器函數 | `iterate(genFn)` |
|
|
95
|
+
| 函數 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
96
|
+
|------|------|------------|------------|
|
|
97
|
+
| `useCompare<T>(t1: T, t2: T): number` | 通用比較函數 | O(1) | O(1) |
|
|
98
|
+
| `useRandom<T = number | bigint>(index: T): T` | 偽隨機數生成器 | O(log n) | O(1) |
|
|
86
99
|
|
|
87
|
-
|
|
100
|
+
```typescript
|
|
101
|
+
// 工具函數使用示例
|
|
102
|
+
const numbers = [3, 1, 4, 1, 5];
|
|
103
|
+
numbers.sort(useCompare); // [1, 1, 3, 4, 5]
|
|
88
104
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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)` |
|
|
105
|
+
const randomNum = useRandom(42); // 基於種子的隨機數
|
|
106
|
+
const randomBigInt = useRandom(1000n); // BigInt 隨機數
|
|
107
|
+
```
|
|
104
108
|
|
|
105
|
-
|
|
109
|
+
## 工廠方法
|
|
106
110
|
|
|
107
|
-
###
|
|
111
|
+
### Optional 工廠方法
|
|
108
112
|
|
|
109
|
-
|
|
113
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
114
|
+
|------|------|------------|------------|
|
|
115
|
+
| `Optional.empty<T>()` | 創建空的 Optional | O(1) | O(1) |
|
|
116
|
+
| `Optional.of<T>(value)` | 創建包含值的 Optional | O(1) | O(1) |
|
|
117
|
+
| `Optional.ofNullable<T>(value)` | 創建可能為空的 Optional | O(1) | O(1) |
|
|
118
|
+
| `Optional.ofNonNull<T>(value)` | 創建非空的 Optional | O(1) | O(1) |
|
|
110
119
|
|
|
111
120
|
```typescript
|
|
112
|
-
|
|
121
|
+
// Optional 使用示例
|
|
122
|
+
const emptyOpt = Optional.empty<number>();
|
|
123
|
+
const presentOpt = Optional.of(42);
|
|
124
|
+
const nullableOpt = Optional.ofNullable<string>(null);
|
|
125
|
+
const nonNullOpt = Optional.ofNonNull("hello");
|
|
126
|
+
|
|
127
|
+
presentOpt.ifPresent(val => console.log(val)); // 輸出 42
|
|
128
|
+
console.log(emptyOpt.orElse(100)); // 輸出 100
|
|
113
129
|
```
|
|
114
130
|
|
|
115
|
-
|
|
116
|
-
當資料的順序不重要,而您追求極致效能時,這是最佳選擇。
|
|
117
|
-
|
|
118
|
-
---
|
|
131
|
+
### Collector 工廠方法
|
|
119
132
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
134
|
+
|------|------|------------|------------|
|
|
135
|
+
| `Collector.full(identity, accumulator, finisher)` | 創建完整收集器 | O(1) | O(1) |
|
|
136
|
+
| `Collector.shortable(identity, interruptor, accumulator, finisher)` | 創建可中斷收集器 | O(1) | O(1) |
|
|
123
137
|
|
|
124
138
|
```typescript
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
139
|
+
// Collector 使用示例
|
|
140
|
+
const sumCollector = Collector.full(
|
|
141
|
+
() => 0,
|
|
142
|
+
(sum, num) => sum + num,
|
|
143
|
+
result => result
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const numbers = from([1, 2, 3, 4, 5]);
|
|
147
|
+
const total = numbers.toUnoredered().collect(sumCollector); // 15
|
|
128
148
|
```
|
|
129
149
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
---
|
|
150
|
+
### Semantic 工廠方法
|
|
133
151
|
|
|
134
|
-
|
|
152
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
153
|
+
|------|------|------------|------------|
|
|
154
|
+
| `blob(blob, chunkSize)` | 從 Blob 建立串流 | O(n) | O(chunkSize) |
|
|
155
|
+
| `empty<E>()` | 建立空串流 | O(1) | O(1) |
|
|
156
|
+
| `fill<E>(element, count)` | 建立填充串流 | O(n) | O(1) |
|
|
157
|
+
| `from<E>(iterable)` | 從可迭代物件建立串流 | O(1) | O(1) |
|
|
158
|
+
| `interval(period, delay?)` | 建立定時間隔串流 | O(1)* | O(1) |
|
|
159
|
+
| `iterate<E>(generator)` | 從產生器建立串流 | O(1) | O(1) |
|
|
160
|
+
| `range(start, end, step)` | 建立數值範圍串流 | O(n) | O(1) |
|
|
161
|
+
| `websocket(websocket)` | 從 WebSocket 建立串流 | O(1) | O(1) |
|
|
135
162
|
|
|
136
|
-
|
|
163
|
+
```typescript
|
|
164
|
+
// Semantic 工廠方法使用範例
|
|
165
|
+
|
|
166
|
+
// 從 Blob 建立串流(分塊讀取)
|
|
167
|
+
blob(someBlob, 1024n)
|
|
168
|
+
.toUnordered()
|
|
169
|
+
.write(WritableStream)
|
|
170
|
+
.then(callback) // 串流寫入成功
|
|
171
|
+
.catch(writeFi); // 串流寫入失敗
|
|
172
|
+
|
|
173
|
+
// 建立空串流,僅在與其他串流連接後才會執行
|
|
174
|
+
empty<string>()
|
|
175
|
+
.toUnordered()
|
|
176
|
+
.join(); //[]
|
|
177
|
+
|
|
178
|
+
// 建立填充串流
|
|
179
|
+
const filledStream = fill("hello", 3); // "hello", "hello", "hello"
|
|
180
|
+
|
|
181
|
+
// 建立初始延遲2秒、執行週期5秒的時序串流,
|
|
182
|
+
// 基於計時器機制實現,因系統排程限制可能產生時間漂移
|
|
183
|
+
const intervalStream = interval(5000, 2000);
|
|
184
|
+
|
|
185
|
+
// 從可迭代物件建立串流
|
|
186
|
+
const numberStream = from([1, 2, 3, 4, 5]);
|
|
187
|
+
const stringStream = from(new Set(["Alex", "Bob"]));
|
|
188
|
+
|
|
189
|
+
// 建立範圍串流
|
|
190
|
+
const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
191
|
+
|
|
192
|
+
// WebSocket 事件串流
|
|
193
|
+
const ws = new WebSocket("ws://localhost:8080");
|
|
194
|
+
websocket(ws)
|
|
195
|
+
.filter((event)=> event.type === "message") // 僅監聽訊息事件
|
|
196
|
+
.toUnordered() // 事件通常不排序
|
|
197
|
+
.forEach((event)=> receive(event)); // 接收訊息
|
|
198
|
+
```
|
|
137
199
|
|
|
138
|
-
|
|
200
|
+
## Semantic 類方法
|
|
201
|
+
|
|
202
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
203
|
+
|------|------|------------|------------|
|
|
204
|
+
| `concat(other)` | 連接兩個流 | O(n) | O(1) |
|
|
205
|
+
| `distinct()` | 去重 | O(n) | O(n) |
|
|
206
|
+
| `distinct(comparator)` | 使用比較器去重 | O(n²) | O(n) |
|
|
207
|
+
| `dropWhile(predicate)` | 丟棄滿足條件的元素 | O(n) | O(1) |
|
|
208
|
+
| `filter(predicate)` | 過濾元素 | O(n) | O(1) |
|
|
209
|
+
| `flat(mapper)` | 扁平化映射 | O(n × m) | O(1) |
|
|
210
|
+
| `flatMap(mapper)` | 扁平化映射到新型別 | O(n × m) | O(1) |
|
|
211
|
+
| `limit(n)` | 限制元素數量 | O(n) | O(1) |
|
|
212
|
+
| `map(mapper)` | 映射轉換 | O(n) | O(1) |
|
|
213
|
+
| `peek(consumer)` | 查看元素 | O(n) | O(1) |
|
|
214
|
+
| `redirect(redirector)` | 重定向索引 | O(n) | O(1) |
|
|
215
|
+
| `reverse()` | 反轉流 | O(n) | O(1) |
|
|
216
|
+
| `shuffle()` | 隨機打亂 | O(n) | O(1) |
|
|
217
|
+
| `shuffle(mapper)` | 使用映射器打亂 | O(n) | O(1) |
|
|
218
|
+
| `skip(n)` | 跳過前n個元素 | O(n) | O(1) |
|
|
219
|
+
| `sorted()` | 排序 | O(n log n) | O(n) |
|
|
220
|
+
| `sorted(comparator)` | 使用比較器排序 | O(n log n) | O(n) |
|
|
221
|
+
| `sub(start, end)` | 獲取子流 | O(n) | O(1) |
|
|
222
|
+
| `takeWhile(predicate)` | 獲取滿足條件的元素 | O(n) | O(1) |
|
|
223
|
+
| `translate(offset)` | 平移索引 | O(n) | O(1) |
|
|
224
|
+
| `translate(translator)` | 使用轉換器平移索引 | O(n) | O(1) |
|
|
139
225
|
|
|
140
226
|
```typescript
|
|
141
|
-
|
|
142
|
-
|
|
227
|
+
// Semantic 操作示例
|
|
228
|
+
const result = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
229
|
+
.filter(n => n % 2 === 0) // 過濾偶數
|
|
230
|
+
.map(n => n * 2) // 乘以2
|
|
231
|
+
.skip(1) // 跳過第一個
|
|
232
|
+
.limit(3) // 限制3個元素
|
|
233
|
+
.toArray(); // 轉換為陣列
|
|
234
|
+
// 結果: [8, 12, 20]
|
|
235
|
+
|
|
236
|
+
// 複雜操作示例
|
|
237
|
+
const complexResult = range(1, 100, 1)
|
|
238
|
+
.flatMap(n => from([n, n * 2])) // 每個元素映射為兩個
|
|
239
|
+
.distinct() // 去重
|
|
240
|
+
.shuffle() // 打亂順序
|
|
241
|
+
.takeWhile(n => n < 50) // 取小於50的元素
|
|
242
|
+
.toOrdered() // 轉換為有序收集器
|
|
243
|
+
.toArray(); // 轉換為陣列
|
|
143
244
|
```
|
|
144
245
|
|
|
145
|
-
|
|
246
|
+
## 收集器轉換方法
|
|
146
247
|
|
|
147
|
-
|
|
248
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
249
|
+
|------|------|------------|------------|
|
|
250
|
+
| `toUnoredered()` | 轉換為無序收集器(效能優先) | O(1) | O(1) |
|
|
251
|
+
| `toOrdered()` | 轉換為有序收集器 | O(1) | O(1) |
|
|
252
|
+
| `sorted()` | 排序並轉換為有序收集器 | O(n log n) | O(n) |
|
|
253
|
+
| `toWindow()` | 轉換為視窗收集器 | O(1) | O(1) |
|
|
254
|
+
| `toNumericStatistics()` | 轉換為數值統計 | O(1) | O(1) |
|
|
255
|
+
| `toBigintStatistics()` | 轉換為大數統計 | O(1) | O(1) |
|
|
148
256
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
257
|
+
```typescript
|
|
258
|
+
// 收集器轉換示例
|
|
259
|
+
const numbers = from([3, 1, 4, 1, 5, 9, 2, 6, 5]);
|
|
152
260
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
261
|
+
// 效能優先:使用無序收集器
|
|
262
|
+
const unordered = numbers
|
|
263
|
+
.filter(n => n > 3)
|
|
264
|
+
.toUnoredered();
|
|
157
265
|
|
|
158
|
-
|
|
266
|
+
// 需要排序:使用有序收集器
|
|
267
|
+
const ordered = numbers.sorted();
|
|
159
268
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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)` |
|
|
269
|
+
// 統計分析:使用統計收集器
|
|
270
|
+
const stats = numbers
|
|
271
|
+
.toNumericStatistics();
|
|
170
272
|
|
|
171
|
-
|
|
273
|
+
console.log(stats.mean()); // 平均值
|
|
274
|
+
console.log(stats.median()); // 中位數
|
|
275
|
+
console.log(stats.standardDeviation()); // 標準差
|
|
172
276
|
|
|
173
|
-
|
|
277
|
+
// 視窗操作
|
|
278
|
+
const windowed = numbers
|
|
279
|
+
.toWindow()
|
|
280
|
+
.tumble(3n); // 每3個元素一個視窗
|
|
174
281
|
|
|
175
|
-
|
|
282
|
+
windowed.forEach(window => {
|
|
283
|
+
console.log(window.toArray()); // 每個視窗的內容
|
|
284
|
+
});
|
|
285
|
+
```
|
|
176
286
|
|
|
177
|
-
|
|
287
|
+
## Collectable 收集方法
|
|
288
|
+
|
|
289
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
290
|
+
|------|------|------------|------------|
|
|
291
|
+
| `anyMatch(predicate)` | 是否存在匹配元素 | O(n) | O(1) |
|
|
292
|
+
| `allMatch(predicate)` | 是否所有元素匹配 | O(n) | O(1) |
|
|
293
|
+
| `count()` | 元素計數 | O(n) | O(1) |
|
|
294
|
+
| `isEmpty()` | 是否為空 | O(1) | O(1) |
|
|
295
|
+
| `findAny()` | 查找任意元素 | O(n) | O(1) |
|
|
296
|
+
| `findFirst()` | 查找第一個元素 | O(n) | O(1) |
|
|
297
|
+
| `findLast()` | 查找最後一個元素 | O(n) | O(1) |
|
|
298
|
+
| `forEach(action)` | 遍歷所有元素 | O(n) | O(1) |
|
|
299
|
+
| `group(classifier)` | 按分類器分組 | O(n) | O(n) |
|
|
300
|
+
| `groupBy(keyExtractor, valueExtractor)` | 按鍵值提取器分組 | O(n) | O(n) |
|
|
301
|
+
| `join()` | 連接為字串 | O(n) | O(n) |
|
|
302
|
+
| `join(delimiter)` | 使用分隔符連接 | O(n) | O(n) |
|
|
303
|
+
| `nonMatch(predicate)` | 是否沒有元素匹配 | O(n) | O(1) |
|
|
304
|
+
| `partition(count)` | 按數量分區 | O(n) | O(n) |
|
|
305
|
+
| `partitionBy(classifier)` | 按分類器分區 | O(n) | O(n) |
|
|
306
|
+
| `reduce(accumulator)` | 歸約操作 | O(n) | O(1) |
|
|
307
|
+
| `reduce(identity, accumulator)` | 帶初始值的歸約 | O(n) | O(1) |
|
|
308
|
+
| `toArray()` | 轉換為陣列 | O(n) | O(n) |
|
|
309
|
+
| `toMap(keyExtractor, valueExtractor)` | 轉換為Map | O(n) | O(n) |
|
|
310
|
+
| `toSet()` | 轉換為Set | O(n) | O(n) |
|
|
311
|
+
| `write(stream)` | 寫入流 | O(n) | O(1) |
|
|
178
312
|
|
|
179
313
|
```typescript
|
|
180
|
-
|
|
181
|
-
const
|
|
314
|
+
// Collectable 操作示例
|
|
315
|
+
const data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
316
|
+
.filter(n => n % 2 === 0)
|
|
317
|
+
.toOrdered();
|
|
318
|
+
|
|
319
|
+
// 匹配檢查
|
|
320
|
+
console.log(data.anyMatch(n => n > 5)); // true
|
|
321
|
+
console.log(data.allMatch(n => n < 20)); // true
|
|
322
|
+
|
|
323
|
+
// 查找操作
|
|
324
|
+
data.findFirst().ifPresent(n => console.log(n)); // 2
|
|
325
|
+
data.findAny().ifPresent(n => console.log(n)); // 任意元素
|
|
326
|
+
|
|
327
|
+
// 分組操作
|
|
328
|
+
const grouped = data.groupBy(
|
|
329
|
+
n => n > 5 ? "large" : "small",
|
|
330
|
+
n => n * 2
|
|
331
|
+
);
|
|
332
|
+
// {small: [4, 8], large: [12, 16, 20]}
|
|
333
|
+
|
|
334
|
+
// 歸約操作
|
|
335
|
+
const sum = data.reduce(0, (acc, n) => acc + n); // 30
|
|
336
|
+
|
|
337
|
+
// 輸出操作
|
|
338
|
+
data.join(", "); // "2, 4, 6, 8, 10"
|
|
182
339
|
```
|
|
183
340
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
341
|
+
## 統計分析方法
|
|
342
|
+
|
|
343
|
+
### NumericStatistics 方法
|
|
344
|
+
|
|
345
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
346
|
+
|------|------|------------|------------|
|
|
347
|
+
| `range()` | 極差 | O(n) | O(1) |
|
|
348
|
+
| `variance()` | 方差 | O(n) | O(1) |
|
|
349
|
+
| `standardDeviation()` | 標準差 | O(n) | O(1) |
|
|
350
|
+
| `mean()` | 平均值 | O(n) | O(1) |
|
|
351
|
+
| `median()` | 中位數 | O(n log n) | O(n) |
|
|
352
|
+
| `mode()` | 眾數 | O(n) | O(n) |
|
|
353
|
+
| `frequency()` | 頻率分佈 | O(n) | O(n) |
|
|
354
|
+
| `summate()` | 求和 | O(n) | O(1) |
|
|
355
|
+
| `quantile(quantile)` | 分位數 | O(n log n) | O(n) |
|
|
356
|
+
| `interquartileRange()` | 四分位距 | O(n log n) | O(n) |
|
|
357
|
+
| `skewness()` | 偏度 | O(n) | O(1) |
|
|
358
|
+
| `kurtosis()` | 峰度 | O(n) | O(1) |
|
|
191
359
|
|
|
192
360
|
```typescript
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
361
|
+
// 統計分析示例
|
|
362
|
+
const numbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
363
|
+
.toNumericStatistics();
|
|
364
|
+
|
|
365
|
+
console.log("平均值:", numbers.mean()); // 5.5
|
|
366
|
+
console.log("中位數:", numbers.median()); // 5.5
|
|
367
|
+
console.log("標準差:", numbers.standardDeviation()); // ~2.87
|
|
368
|
+
console.log("總和:", numbers.summate()); // 55
|
|
369
|
+
|
|
370
|
+
// 使用映射器的統計分析
|
|
371
|
+
const objects = from([
|
|
372
|
+
{ value: 10 },
|
|
373
|
+
{ value: 20 },
|
|
374
|
+
{ value: 30 }
|
|
375
|
+
]).toNumericStatistics();
|
|
376
|
+
|
|
377
|
+
console.log("映射平均值:", objects.mean(obj => obj.value)); // 20
|
|
196
378
|
```
|
|
197
379
|
|
|
198
|
-
|
|
199
|
-
✅ **當資料順序不重要時,提供最快速的處理方式**
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
### 9. `Statistics<E, D>` — 統計分析
|
|
204
|
-
|
|
205
|
-
用於分析數值資料的抽象基礎類別。
|
|
206
|
-
|
|
207
|
-
#### 子類別:
|
|
208
|
-
|
|
209
|
-
- `NumericStatistics<E>` — 適用於 `number` 類型
|
|
210
|
-
- `BigIntStatistics<E>` — 適用於 `bigint` 類型
|
|
211
|
-
|
|
212
|
-
##### 常見統計方法:
|
|
213
|
-
|
|
214
|
-
| 方法 | 說明 | 範例 |
|
|
215
|
-
|------|------|------|
|
|
216
|
-
| `mean()` | 平均值 | `.mean()` |
|
|
217
|
-
| `median()` | 中位數 | `.median()` |
|
|
218
|
-
| `mode()` | 眾數(最常出現的值) | `.mode()` |
|
|
219
|
-
| `minimum()` | 最小值 | `.minimum()` |
|
|
220
|
-
| `maximum()` | 最大值 | `.maximum()` |
|
|
221
|
-
| `range()` | 範圍(最大值 - 最小值) | `.range()` |
|
|
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
|
-
## 🧪 完整範例
|
|
380
|
+
## 效能選擇指南
|
|
231
381
|
|
|
382
|
+
### 選擇無序收集器(效能優先)
|
|
232
383
|
```typescript
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
// 🚀 最快:不排序
|
|
239
|
-
const fastest = numbers.toUnordered();
|
|
240
|
-
console.log(fastest.toArray()); // 例如:[10, 2, 8, 4, 5, 6](原始順序)
|
|
241
|
-
|
|
242
|
-
// 🔢 自然排序
|
|
243
|
-
const ordered = numbers.sorted();
|
|
244
|
-
console.log(ordered.toArray()); // [2, 4, 5, 6, 8, 10]
|
|
245
|
-
|
|
246
|
-
// 📊 統計分析
|
|
247
|
-
const stats = new NumericStatistics(numbers);
|
|
248
|
-
console.log('平均值:', stats.mean());
|
|
249
|
-
console.log('中位數:', stats.median());
|
|
250
|
-
console.log('眾數:', stats.mode());
|
|
251
|
-
console.log('範圍:', stats.range());
|
|
252
|
-
console.log('標準差:', stats.standardDeviation());
|
|
384
|
+
// 當不需要順序保證時,使用無序收集器獲得最佳效能
|
|
385
|
+
const highPerformance = data
|
|
386
|
+
.filter(predicate)
|
|
387
|
+
.map(mapper)
|
|
388
|
+
.toUnoredered(); // 最佳效能
|
|
253
389
|
```
|
|
254
390
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
## 🛠️ 工具函數
|
|
258
|
-
|
|
259
|
-
本套件也提供多種**型別守衛(Type Guards)**與**比較工具**:
|
|
260
|
-
|
|
261
|
-
| 函數 | 用途 |
|
|
262
|
-
|------|------|
|
|
263
|
-
| `isString(x)` | 判斷是否為 `string` |
|
|
264
|
-
| `isNumber(x)` | 判斷是否為 `number` |
|
|
265
|
-
| `isBoolean(x)` | 判斷是否為 `boolean` |
|
|
266
|
-
| `isIterable(x)` | 判斷是否為可迭代物件 |
|
|
267
|
-
| `useCompare(a, b)` | 通用比較函數 |
|
|
268
|
-
| `useRandom(x)` | 偽隨機數生成器(趣味用途) |
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## 🧩 進階:自訂生成器與滑動視窗
|
|
273
|
-
|
|
274
|
-
您可以建立**自訂的資料生成器**,用於控制或無限的資料流:
|
|
275
|
-
|
|
391
|
+
### 選擇有序收集器(需要順序)
|
|
276
392
|
```typescript
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (i === 5) interrupt(i);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
const s = new Semantic(gen);
|
|
393
|
+
// 當需要保持元素順序時,使用有序收集器
|
|
394
|
+
const ordered = data
|
|
395
|
+
.sorted(comparator) // 排序操作會覆蓋重定向效果
|
|
285
396
|
```
|
|
286
397
|
|
|
287
|
-
|
|
288
|
-
|
|
398
|
+
### 選擇視窗收集器(視窗操作)
|
|
289
399
|
```typescript
|
|
290
|
-
|
|
400
|
+
// 需要進行視窗操作時
|
|
401
|
+
const windowed = data
|
|
402
|
+
.toWindow()
|
|
403
|
+
.slide(5n, 2n); // 滑動視窗
|
|
291
404
|
```
|
|
292
405
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
---
|
|
300
|
-
|
|
301
|
-
## 🙌 貢獻
|
|
302
|
-
|
|
303
|
-
歡迎提交 Pull Request、提出問題(Issues)或分享想法!
|
|
304
|
-
|
|
305
|
-
---
|
|
306
|
-
|
|
307
|
-
## 🚀 快速入門總覽
|
|
308
|
-
|
|
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()` 等 |
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
|
-
## 🔗 相關連結
|
|
406
|
+
### 選擇統計分析(數值計算)
|
|
407
|
+
```typescript
|
|
408
|
+
// 需要進行統計分析時
|
|
409
|
+
const stats = data
|
|
410
|
+
.toNumericStatistics(); // 數值統計
|
|
322
411
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
412
|
+
const bigIntStats = data
|
|
413
|
+
.toBigintStatistics(); // 大數統計
|
|
414
|
+
```
|
|
326
415
|
|
|
327
|
-
|
|
416
|
+
[GitHub](https://github.com/eloyhere/semantic-typescript)
|
|
417
|
+
[NPMJS](https://www.npmjs.com/package/semantic-typescript)
|
|
328
418
|
|
|
329
|
-
|
|
419
|
+
## 注意事項
|
|
330
420
|
|
|
331
|
-
|
|
421
|
+
1. **排序操作的影響**:在有序收集器中,`sorted()` 操作會覆蓋 `redirect`、`translate`、`shuffle`、`reverse` 的效果
|
|
422
|
+
2. **效能考慮**:如果不需要順序保證,優先使用 `toUnoredered()` 獲得更好效能
|
|
423
|
+
3. **記憶體使用**:排序操作需要 O(n) 的額外空間
|
|
424
|
+
4. **實時數據**:Semantic 流適合處理實時數據,支援非同步數據源
|
|
332
425
|
|
|
333
|
-
|
|
334
|
-
- `toUnordered()` → **不排序,最快**
|
|
335
|
-
- 其他方法(如 `sorted()`、`toOrdered()`)→ **會進行排序**
|
|
426
|
+
這個庫為 TypeScript 開發者提供了強大而靈活的流式處理能力,結合了函數式編程的優點和類型安全的保障。
|