semantic-typescript 0.0.8 → 0.2.5
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/collectable.d.ts +84 -0
- package/dist/collectable.js +476 -0
- package/dist/collector.d.ts +24 -0
- package/dist/collector.js +63 -0
- package/dist/factory.d.ts +11 -0
- package/dist/factory.js +248 -0
- package/dist/guard.d.ts +23 -0
- package/dist/guard.js +85 -0
- package/dist/hook.d.ts +2 -0
- package/dist/hook.js +64 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/optional.d.ts +18 -0
- package/dist/optional.js +65 -0
- package/dist/semantic.d.ts +9 -272
- package/dist/semantic.js +38 -1679
- package/dist/statistics.d.ts +101 -0
- package/dist/statistics.js +765 -0
- package/dist/symbol.d.ts +10 -0
- package/dist/symbol.js +10 -0
- package/dist/utility.d.ts +49 -0
- package/dist/utility.js +17 -0
- package/package.json +54 -8
- package/readme.cn.md +387 -445
- package/readme.de.md +393 -448
- package/readme.es.md +392 -446
- package/readme.fr.md +396 -450
- package/readme.jp.md +390 -447
- package/readme.kr.md +396 -453
- package/readme.md +389 -445
- package/readme.ru.md +391 -447
- package/readme.tw.md +403 -444
package/readme.tw.md
CHANGED
|
@@ -1,529 +1,488 @@
|
|
|
1
|
-
# Semantic-TypeScript
|
|
1
|
+
# Semantic-TypeScript 流處理庫
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 簡介
|
|
4
4
|
|
|
5
|
-
Semantic-TypeScript
|
|
5
|
+
Semantic-TypeScript 是一個受到 JavaScript GeneratorFunction、Java Stream 和 MySQL Index 啟發而設計的現代化流處理庫。該庫的核心設計理念是基於數據索引建構高效的數據處理管道,為前端開發提供類型安全、函數式風格的流式操作體驗。
|
|
6
6
|
|
|
7
|
-
與傳統的同步處理不同,Semantic
|
|
7
|
+
與傳統的同步處理不同,Semantic 採用非同步處理模式。在創建數據流時,終端接收數據的時間完全取決於上游何時調用 `accept` 和 `interrupt` 回調函數,這種設計使得庫能夠優雅地處理實時數據流、大型數據集和非同步數據源。
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 安裝
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
### 串流建立工廠
|
|
11
|
+
```bash
|
|
12
|
+
npm install semantic-typescript
|
|
13
|
+
```
|
|
38
14
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
15
|
+
## 基礎類型
|
|
16
|
+
|
|
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
|
+
|
|
35
|
+
## 函式介面
|
|
36
|
+
|
|
37
|
+
| 介面 | 描述 |
|
|
38
|
+
|------|-------------|
|
|
39
|
+
| `Runnable` | 無參數且無回傳值的函式 |
|
|
40
|
+
| `Supplier<R>` | 無參數並回傳 `R` 的函式 |
|
|
41
|
+
| `Functional<T, R>` | 單參數轉換函式 |
|
|
42
|
+
| `BiFunctional<T, U, R>` | 雙參數轉換函式 |
|
|
43
|
+
| `TriFunctional<T, U, V, R>` | 三參數轉換函式 |
|
|
44
|
+
| `Predicate<T>` | 單參數判斷函式 |
|
|
45
|
+
| `BiPredicate<T, U>` | 雙參數判斷函式 |
|
|
46
|
+
| `TriPredicate<T, U, V>` | 三參數判斷函式 |
|
|
47
|
+
| `Consumer<T>` | 單參數消費函式 |
|
|
48
|
+
| `BiConsumer<T, U>` | 雙參數消費函式 |
|
|
49
|
+
| `TriConsumer<T, U, V>` | 三參數消費函式 |
|
|
50
|
+
| `Comparator<T>` | 雙參數比較函式 |
|
|
51
|
+
| `Generator<T>` | 產生器函式(核心與基礎) |
|
|
48
52
|
|
|
49
|
-
**程式碼範例補充:**
|
|
50
53
|
```typescript
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
// 建立數值範圍串流
|
|
57
|
-
const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
58
|
-
|
|
59
|
-
// 填充重複元素
|
|
60
|
-
const filledStream = fill("hello", 3n); // "hello", "hello", "hello"
|
|
61
|
-
|
|
62
|
-
// 建立空串流
|
|
63
|
-
const emptyStream = empty<number>();
|
|
54
|
+
// 類型使用示例
|
|
55
|
+
const predicate: Predicate<number> = (n) => n > 0;
|
|
56
|
+
const mapper: Functional<string, number> = (str) => str.length;
|
|
57
|
+
const comparator: Comparator<number> = (a, b) => a - b;
|
|
64
58
|
```
|
|
65
59
|
|
|
66
|
-
|
|
60
|
+
## 類型守衛
|
|
61
|
+
|
|
62
|
+
| 函數 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
63
|
+
|------|------|------------|------------|
|
|
64
|
+
| `validate<T>(t: MaybeInvalid<T>): t is T` | 驗證值不為 null 或 undefined | O(1) | O(1) |
|
|
65
|
+
| `invalidate<T>(t: MaybeInvalid<T>): t is null \| undefined` | 驗證值為 null 或 undefined | O(1) | O(1) |
|
|
66
|
+
| `isBoolean(t: unknown): t is boolean` | 檢查是否為布林值 | O(1) | O(1) |
|
|
67
|
+
| `isString(t: unknown): t is string` | 檢查是否為字串 | O(1) | O(1) |
|
|
68
|
+
| `isNumber(t: unknown): t is number` | 檢查是否為數字 | O(1) | O(1) |
|
|
69
|
+
| `isFunction(t: unknown): t is Function` | 檢查是否為函數 | O(1) | O(1) |
|
|
70
|
+
| `isObject(t: unknown): t is object` | 檢查是否為物件 | O(1) | O(1) |
|
|
71
|
+
| `isSymbol(t: unknown): t is symbol` | 檢查是否為 Symbol | O(1) | O(1) |
|
|
72
|
+
| `isBigint(t: unknown): t is bigint` | 檢查是否為 BigInt | O(1) | O(1) |
|
|
73
|
+
| `isPrimitive(t: unknown): t is Primitive` | 檢查是否為原始類型 | O(1) | O(1) |
|
|
74
|
+
| `isIterable(t: unknown): t is Iterable<unknown>` | 檢查是否為可迭代物件 | O(1) | O(1) |
|
|
75
|
+
| `isOptional(t: unknown): t is Optional<unknown>` | 檢查是否為 Optional 實例 | O(1) | O(1) |
|
|
76
|
+
| `isSemantic(t: unknown): t is Semantic<unknown>` | 檢查是否為 Semantic 實例 | O(1) | O(1) |
|
|
77
|
+
| `isCollector(t: unknown): t is Collector<unknown, unknown, unknown>` | 檢查是否為 Collector 實例 | O(1) | O(1) |
|
|
78
|
+
| `isCollectable(t: unknown): t is Collectable<unknown>` | 檢查是否為 Collectable 實例 | O(1) | O(1) |
|
|
79
|
+
| `isOrderedCollectable(t: unknown): t is OrderedCollectable<unknown>` | 檢查是否為 OrderedCollectable 實例 | O(1) | O(1) |
|
|
80
|
+
| `isWindowCollectable(t: unknown): t is WindowCollectable<unknown>` | 檢查是否為 WindowCollectable 實例 | O(1) | O(1) |
|
|
81
|
+
| `isUnorderedCollectable(t: unknown): t is UnorderedCollectable<unknown>` | 檢查是否為 UnorderedCollectable 實例 | O(1) | O(1) |
|
|
82
|
+
| `isStatistics(t: unknown): t is Statistics<unknown, number \| bigint>` | 檢查是否為 Statistics 實例 | O(1) | O(1) |
|
|
83
|
+
| `isNumericStatistics(t: unknown): t is NumericStatistics<unknown>` | 檢查是否為 NumericStatistics 實例 | O(1) | O(1) |
|
|
84
|
+
| `isBigIntStatistics(t: unknown): t is BigIntStatistics<unknown>` | 檢查是否為 BigIntStatistics 實例 | O(1) | O(1) |
|
|
67
85
|
|
|
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)` → 隨機數 |
|
|
74
|
-
|
|
75
|
-
**程式碼範例補充:**
|
|
76
86
|
```typescript
|
|
77
|
-
|
|
87
|
+
// 類型守衛使用示例
|
|
88
|
+
const value: unknown = "hello";
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (validate(data)) {
|
|
82
|
-
console.log(data.toUpperCase()); // 安全呼叫,因為 validate 確保資料不為 null
|
|
90
|
+
if (isString(value)) {
|
|
91
|
+
console.log(value.length); // 類型安全,value 被推斷為 string
|
|
83
92
|
}
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
console.log("資料無效"); // 會執行,因為 invalidate 檢測到 null
|
|
94
|
+
if (isOptional(someValue)) {
|
|
95
|
+
someValue.ifPresent(val => console.log(val));
|
|
88
96
|
}
|
|
89
|
-
|
|
90
|
-
// 比較值
|
|
91
|
-
const comparison = useCompare("apple", "banana"); // -1
|
|
92
|
-
|
|
93
|
-
// 產生隨機數
|
|
94
|
-
const randomNum = useRandom(42); // 基於種子 42 的隨機數
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
##
|
|
98
|
-
|
|
99
|
-
### Optional<T> - 安全空值處理
|
|
99
|
+
## 工具函數
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
| 函數 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
102
|
+
|------|------|------------|------------|
|
|
103
|
+
| `useCompare<T>(t1: T, t2: T): number` | 通用比較函數 | O(1) | O(1) |
|
|
104
|
+
| `useRandom<T = number | bigint>(index: T): T` | 偽隨機數生成器 | O(log n) | O(1) |
|
|
102
105
|
|
|
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) |
|
|
115
|
-
|
|
116
|
-
**程式碼範例補充:**
|
|
117
106
|
```typescript
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
const optionalValue = Optional.ofNullable<string>(Math.random() > 0.5 ? "hello" : null);
|
|
107
|
+
// 工具函數使用示例
|
|
108
|
+
const numbers = [3, 1, 4, 1, 5];
|
|
109
|
+
numbers.sort(useCompare); // [1, 1, 3, 4, 5]
|
|
122
110
|
|
|
123
|
-
//
|
|
124
|
-
const
|
|
125
|
-
.filter(val => val.length > 3) // 過濾長度大於 3 的值
|
|
126
|
-
.map(val => val.toUpperCase()) // 轉換為大寫
|
|
127
|
-
.getOrDefault("default"); // 獲取值或預設值
|
|
128
|
-
|
|
129
|
-
console.log(result); // "HELLO" 或 "default"
|
|
130
|
-
|
|
131
|
-
// 安全操作
|
|
132
|
-
optionalValue.ifPresent(val => {
|
|
133
|
-
console.log(`值存在: ${val}`);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// 檢查狀態
|
|
137
|
-
if (optionalValue.isPresent()) {
|
|
138
|
-
console.log("有值");
|
|
139
|
-
} else if (optionalValue.isEmpty()) {
|
|
140
|
-
console.log("為空");
|
|
141
|
-
}
|
|
111
|
+
const randomNum = useRandom(42); // 基於種子的隨機數
|
|
112
|
+
const randomBigInt = useRandom(1000n); // BigInt 隨機數
|
|
142
113
|
```
|
|
143
114
|
|
|
144
|
-
|
|
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
|
-
**程式碼範例補充:**
|
|
173
|
-
```typescript
|
|
174
|
-
import { from } from 'semantic-typescript';
|
|
115
|
+
## 工廠方法
|
|
175
116
|
|
|
176
|
-
|
|
117
|
+
### Optional 工廠方法
|
|
177
118
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
.peek((val, index) => console.log(`元素 ${val} 在索引 ${index}`)); // 檢視元素
|
|
119
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
120
|
+
|------|------|------------|------------|
|
|
121
|
+
| `Optional.empty<T>()` | 創建空的 Optional | O(1) | O(1) |
|
|
122
|
+
| `Optional.of<T>(value)` | 創建包含值的 Optional | O(1) | O(1) |
|
|
123
|
+
| `Optional.ofNullable<T>(value)` | 創建可能為空的 Optional | O(1) | O(1) |
|
|
124
|
+
| `Optional.ofNonNull<T>(value)` | 創建非空的 Optional | O(1) | O(1) |
|
|
185
125
|
|
|
186
|
-
|
|
126
|
+
```typescript
|
|
127
|
+
// Optional 使用示例
|
|
128
|
+
const emptyOpt = Optional.empty<number>();
|
|
129
|
+
const presentOpt = Optional.of(42);
|
|
130
|
+
const nullableOpt = Optional.ofNullable<string>(null);
|
|
131
|
+
const nonNullOpt = Optional.ofNonNull("hello");
|
|
132
|
+
|
|
133
|
+
presentOpt.ifPresent(val => console.log(val)); // 輸出 42
|
|
134
|
+
console.log(emptyOpt.orElse(100)); // 輸出 100
|
|
187
135
|
```
|
|
188
136
|
|
|
189
|
-
|
|
137
|
+
### Collector 工廠方法
|
|
190
138
|
|
|
191
|
-
| 方法 |
|
|
192
|
-
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `toWindow()` | `WindowCollectable<E>` | 轉換為視窗集合 | 排序操作,效能較低 |
|
|
196
|
-
| `toNumericStatistics()` | `Statistics<E, number>` | 數值統計分析 | 排序操作,效能較低 |
|
|
197
|
-
| `toBigintStatistics()` | `Statistics<E, bigint>` | 大整數統計分析 | 排序操作,效能較低 |
|
|
198
|
-
| `sorted()` | `OrderedCollectable<E>` | 自然排序 | 覆寫重新導向結果 |
|
|
199
|
-
| `sorted(comparator)` | `OrderedCollectable<E>` | 自訂排序 | 覆寫重新導向結果 |
|
|
139
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
140
|
+
|------|------|------------|------------|
|
|
141
|
+
| `Collector.full(identity, accumulator, finisher)` | 創建完整收集器 | O(1) | O(1) |
|
|
142
|
+
| `Collector.shortable(identity, interruptor, accumulator, finisher)` | 創建可中斷收集器 | O(1) | O(1) |
|
|
200
143
|
|
|
201
|
-
**程式碼範例補充:**
|
|
202
144
|
```typescript
|
|
203
|
-
|
|
145
|
+
// 收集器轉換範例
|
|
146
|
+
const numbers = from([3, 1, 4, 1, 5, 9, 2, 6, 5]);
|
|
204
147
|
|
|
205
|
-
|
|
148
|
+
// 效能優先:使用無序收集器
|
|
149
|
+
const unordered = numbers
|
|
150
|
+
.filter(n => n > 3)
|
|
151
|
+
.toUnoredered();
|
|
206
152
|
|
|
207
|
-
//
|
|
208
|
-
const ordered =
|
|
153
|
+
// 需要排序:使用有序收集器
|
|
154
|
+
const ordered = numbers.sorted();
|
|
209
155
|
|
|
210
|
-
//
|
|
211
|
-
|
|
156
|
+
// 計算元素數量
|
|
157
|
+
let count = Collector.full(
|
|
158
|
+
() => 0, // 初始值
|
|
159
|
+
(accumulator, element) => accumulator + element, // 累積
|
|
160
|
+
(accumulator) => accumulator // 完成
|
|
161
|
+
);
|
|
162
|
+
count.collect(from([1,2,3,4,5])); // 從串流中計數
|
|
163
|
+
count.collect([1,2,3,4,5]); // 從可迭代物件中計數
|
|
164
|
+
|
|
165
|
+
let find = Collector.shortable(
|
|
166
|
+
() => Optional.empty(), // 初始值
|
|
167
|
+
(element, index, accumulator) => accumulator.isPresent(), // 中斷
|
|
168
|
+
(accumulator, element, index) => Optional.of(element), // 累積
|
|
169
|
+
(accumulator) => accumulator // 完成
|
|
170
|
+
);
|
|
171
|
+
find.collect(from([1,2,3,4,5])); // 尋找第一個元素
|
|
172
|
+
find.collect([1,2,3,4,5]); // 尋找第一個元素
|
|
212
173
|
|
|
213
|
-
//
|
|
214
|
-
const
|
|
174
|
+
// 統計分析:使用統計收集器
|
|
175
|
+
const stats = numbers.toNumericStatistics();
|
|
215
176
|
|
|
216
|
-
//
|
|
217
|
-
|
|
177
|
+
console.log(stats.mean()); // 平均值
|
|
178
|
+
console.log(stats.median()); // 中位數
|
|
179
|
+
console.log(stats.standardDeviation()); // 標準差
|
|
218
180
|
|
|
219
|
-
//
|
|
220
|
-
const
|
|
181
|
+
// 視窗操作
|
|
182
|
+
const windowed = numbers
|
|
183
|
+
.toWindow()
|
|
184
|
+
.tumble(3n); // 每 3 個元素形成一個視窗
|
|
221
185
|
|
|
222
|
-
|
|
186
|
+
windowed.forEach(window => {
|
|
187
|
+
console.log(window.toArray()); // 每個視窗的內容
|
|
188
|
+
});
|
|
223
189
|
```
|
|
224
190
|
|
|
225
|
-
###
|
|
191
|
+
### Semantic 工廠方法
|
|
226
192
|
|
|
227
|
-
|
|
193
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
194
|
+
|------|------|------------|------------|
|
|
195
|
+
| `blob(blob, chunkSize)` | 從 Blob 建立串流 | O(n) | O(chunkSize) |
|
|
196
|
+
| `empty<E>()` | 建立空串流 | O(1) | O(1) |
|
|
197
|
+
| `fill<E>(element, count)` | 建立填充串流 | O(n) | O(1) |
|
|
198
|
+
| `from<E>(iterable)` | 從可迭代物件建立串流 | O(1) | O(1) |
|
|
199
|
+
| `generate<E>(element, interrupt)` | 建立產生器串流 | O(1) | O(1) |
|
|
200
|
+
| `interval(period, delay?)` | 建立定時間隔串流 | O(1)* | O(1) |
|
|
201
|
+
| `iterate<E>(generator)` | 從產生器建立串流 | O(1) | O(1) |
|
|
202
|
+
| `range(start, end, step)` | 建立數值範圍串流 | O(n) | O(1) |
|
|
203
|
+
| `websocket(websocket)` | 從 WebSocket 建立串流 | O(1) | O(1) |
|
|
228
204
|
|
|
229
|
-
| 方法 | 描述 | 使用場景 |
|
|
230
|
-
|------|------|----------|
|
|
231
|
-
| `collect(generator)` | 執行資料收集 | 串流終端操作 |
|
|
232
|
-
| `static full(identity, accumulator, finisher)` | 建立完整收集器 | 需要完整處理 |
|
|
233
|
-
| `static shortable(identity, interruptor, accumulator, finisher)` | 建立可中斷收集器 | 可能提前終止 |
|
|
234
|
-
|
|
235
|
-
**程式碼範例補充:**
|
|
236
205
|
```typescript
|
|
237
|
-
|
|
206
|
+
// Semantic 工廠方法使用範例
|
|
238
207
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
208
|
+
// 從 Blob 建立串流(分塊讀取)
|
|
209
|
+
blob(someBlob, 1024n)
|
|
210
|
+
.toUnordered()
|
|
211
|
+
.write(WritableStream)
|
|
212
|
+
.then(callback) // 串流寫入成功
|
|
213
|
+
.catch(writeFi); // 串流寫入失敗
|
|
245
214
|
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
215
|
+
// 建立空串流,僅在與其他串流連接後才會執行
|
|
216
|
+
empty<string>()
|
|
217
|
+
.toUnordered()
|
|
218
|
+
.join(); //[]
|
|
219
|
+
|
|
220
|
+
// 建立填充串流
|
|
221
|
+
const filledStream = fill("hello", 3); // "hello", "hello", "hello"
|
|
222
|
+
|
|
223
|
+
// 建立初始延遲2秒、執行週期5秒的時序串流,
|
|
224
|
+
// 基於計時器機制實現,因系統排程限制可能產生時間漂移
|
|
225
|
+
const intervalStream = interval(5000, 2000);
|
|
250
226
|
|
|
251
|
-
|
|
227
|
+
// 從可迭代物件建立串流
|
|
228
|
+
const numberStream = from([1, 2, 3, 4, 5]);
|
|
229
|
+
const stringStream = from(new Set(["Alex", "Bob"]));
|
|
252
230
|
|
|
253
|
-
|
|
231
|
+
// 建立範圍串流
|
|
232
|
+
const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
254
233
|
|
|
255
|
-
|
|
234
|
+
// WebSocket 事件串流
|
|
235
|
+
const ws = new WebSocket("ws://localhost:8080");
|
|
236
|
+
websocket(ws)
|
|
237
|
+
.filter((event)=> event.type === "message") // 僅監聽訊息事件
|
|
238
|
+
.toUnordered() // 事件通常不排序
|
|
239
|
+
.forEach((event)=> receive(event)); // 接收訊息
|
|
240
|
+
```
|
|
256
241
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
|
260
|
-
|
|
261
|
-
| `
|
|
262
|
-
| `
|
|
263
|
-
| `
|
|
264
|
-
| `
|
|
265
|
-
| `
|
|
242
|
+
## Semantic 類方法
|
|
243
|
+
|
|
244
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
245
|
+
|------|------|------------|------------|
|
|
246
|
+
| `concat(other)` | 連接兩個流 | O(n) | O(1) |
|
|
247
|
+
| `distinct()` | 去重 | O(n) | O(n) |
|
|
248
|
+
| `distinct(comparator)` | 使用比較器去重 | O(n²) | O(n) |
|
|
249
|
+
| `dropWhile(predicate)` | 丟棄滿足條件的元素 | O(n) | O(1) |
|
|
250
|
+
| `filter(predicate)` | 過濾元素 | O(n) | O(1) |
|
|
251
|
+
| `flat(mapper)` | 扁平化映射 | O(n × m) | O(1) |
|
|
252
|
+
| `flatMap(mapper)` | 扁平化映射到新型別 | O(n × m) | O(1) |
|
|
253
|
+
| `limit(n)` | 限制元素數量 | O(n) | O(1) |
|
|
254
|
+
| `map(mapper)` | 映射轉換 | O(n) | O(1) |
|
|
255
|
+
| `peek(consumer)` | 查看元素 | O(n) | O(1) |
|
|
256
|
+
| `redirect(redirector)` | 重定向索引 | O(n) | O(1) |
|
|
257
|
+
| `reverse()` | 反轉流 | O(n) | O(1) |
|
|
258
|
+
| `shuffle()` | 隨機打亂 | O(n) | O(1) |
|
|
259
|
+
| `shuffle(mapper)` | 使用映射器打亂 | O(n) | O(1) |
|
|
260
|
+
| `skip(n)` | 跳過前n個元素 | O(n) | O(1) |
|
|
261
|
+
| `sorted()` | 排序 | O(n log n) | O(n) |
|
|
262
|
+
| `sorted(comparator)` | 使用比較器排序 | O(n log n) | O(n) |
|
|
263
|
+
| `sub(start, end)` | 獲取子流 | O(n) | O(1) |
|
|
264
|
+
| `takeWhile(predicate)` | 獲取滿足條件的元素 | O(n) | O(1) |
|
|
265
|
+
| `translate(offset)` | 平移索引 | O(n) | O(1) |
|
|
266
|
+
| `translate(translator)` | 使用轉換器平移索引 | O(n) | O(1) |
|
|
266
267
|
|
|
267
|
-
**程式碼範例補充:**
|
|
268
268
|
```typescript
|
|
269
|
-
|
|
269
|
+
// Semantic 操作示例
|
|
270
|
+
const result = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
271
|
+
.filter(n => n % 2 === 0) // 過濾偶數
|
|
272
|
+
.map(n => n * 2) // 乘以2
|
|
273
|
+
.skip(1) // 跳過第一個
|
|
274
|
+
.limit(3) // 限制3個元素
|
|
275
|
+
.toArray(); // 轉換為陣列
|
|
276
|
+
// 結果: [8, 12, 20]
|
|
277
|
+
|
|
278
|
+
// 複雜操作示例
|
|
279
|
+
const complexResult = range(1, 100, 1)
|
|
280
|
+
.flatMap(n => from([n, n * 2])) // 每個元素映射為兩個
|
|
281
|
+
.distinct() // 去重
|
|
282
|
+
.shuffle() // 打亂順序
|
|
283
|
+
.takeWhile(n => n < 50) // 取小於50的元素
|
|
284
|
+
.toOrdered() // 轉換為有序收集器
|
|
285
|
+
.toArray(); // 轉換為陣列
|
|
286
|
+
```
|
|
270
287
|
|
|
271
|
-
|
|
288
|
+
## Semantic轉換方法
|
|
272
289
|
|
|
273
|
-
|
|
274
|
-
|
|
290
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
291
|
+
|------------|------------|------------|------------|
|
|
292
|
+
| `sorted()` | 轉為有序收集器 | O(n log n) | O(n) |
|
|
293
|
+
| `toUnordered()` | 轉為無序收集器 | O(1) | O(1) |
|
|
294
|
+
| `toOrdered()` | 轉為有序收集器 | O(1) | O(1) |
|
|
295
|
+
| `toNumericStatistics()` | 轉為數值統計 | O(n) | O(1) |
|
|
296
|
+
| `toBigintStatistics()` | 轉為 bigint 統計 | O(n) | O(1) |
|
|
297
|
+
| `toWindow()` | 轉為視窗收集器 | O(1) | O(1) |
|
|
298
|
+
| `toCollectable()` | 轉為 `UnorderdCollectable` | O(n) | O(1) |
|
|
299
|
+
| `toCollectable(mapper)` | 轉為自訂收集器 | O(n) | O(1) |
|
|
275
300
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
301
|
+
```typescript
|
|
302
|
+
// 轉為升序排序陣列
|
|
303
|
+
from([6,4,3,5,2]) // 建立串流
|
|
304
|
+
.sorted() // 依升序排序串流
|
|
305
|
+
.toArray(); // [2, 3, 4, 5, 6]
|
|
306
|
+
|
|
307
|
+
// 轉為降序排序陣列
|
|
308
|
+
from([6,4,3,5,2]) // 建立串流
|
|
309
|
+
.soted((a, b) => b - a) // 依降序排序串流
|
|
310
|
+
.toArray(); // [6, 5, 4, 3, 2]
|
|
311
|
+
|
|
312
|
+
// 重新導向為反轉陣列
|
|
313
|
+
from([6,4,3,5,2])
|
|
314
|
+
.redirect((element, index) => -index) // 重新導向為反轉順序
|
|
315
|
+
.toOrderd() // 保持重新導向後的順序
|
|
316
|
+
.toArray(); // [2, 5, 3, 4, 6]
|
|
317
|
+
|
|
318
|
+
// 忽略反轉陣列的重新導向
|
|
319
|
+
from([6,4,3,5,2])
|
|
320
|
+
.redirect((element, index) => -index) // 重新導向為反轉順序
|
|
321
|
+
.toUnorderd() // 捨棄重新導向的順序。此操作會忽略 `redirect`、`reverse`、`shuffle` 與 `translate` 操作
|
|
322
|
+
.toArray(); // [2, 5, 3, 4, 6]
|
|
323
|
+
|
|
324
|
+
// 將串流反轉為陣列
|
|
325
|
+
from([6, 4, 3, 5, 2])
|
|
326
|
+
.reverse() // 反轉串流
|
|
327
|
+
.toOrdered() // 保證反轉後的順序
|
|
328
|
+
.toArray(); // [2, 5, 3, 4, 6]
|
|
329
|
+
|
|
330
|
+
// 覆寫洗牌後的串流為陣列
|
|
331
|
+
from([6, 4, 3, 5, 2])
|
|
332
|
+
.shuffle() // 打亂串流
|
|
333
|
+
.sorted() // 覆寫洗牌順序。此操作會覆寫 `redirect`、`reverse`、`shuffle` 與 `translate` 操作
|
|
334
|
+
.toArray(); // [2, 5, 3, 4, 6]
|
|
335
|
+
|
|
336
|
+
// 轉為視窗收集器
|
|
337
|
+
from([6, 4, 3, 5, 2]).toWindow();
|
|
338
|
+
|
|
339
|
+
// 轉為數值統計
|
|
340
|
+
from([6, 4, 3, 5, 2]).toNumericStatistics();
|
|
341
|
+
|
|
342
|
+
// 轉為 bigint 統計
|
|
343
|
+
from([6n, 4n, 3n, 5n, 2n]).toBigintStatistics();
|
|
344
|
+
|
|
345
|
+
// 定義自訂收集器以收集資料
|
|
346
|
+
let customizedCollector = from([1, 2, 3, 4, 5]).toCollectable((generator: Generator<E>) => new CustomizedCollector(generator));
|
|
283
347
|
```
|
|
284
348
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
| 方法 |
|
|
288
|
-
|
|
289
|
-
| `
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
292
|
-
| `
|
|
293
|
-
| `
|
|
294
|
-
| `
|
|
295
|
-
| `
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
| `
|
|
300
|
-
|
|
301
|
-
|
|
349
|
+
## Collectable 收集方法
|
|
350
|
+
|
|
351
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
352
|
+
|------|------|------------|------------|
|
|
353
|
+
| `anyMatch(predicate)` | 是否存在匹配元素 | O(n) | O(1) |
|
|
354
|
+
| `allMatch(predicate)` | 是否所有元素匹配 | O(n) | O(1) |
|
|
355
|
+
| `count()` | 元素計數 | O(n) | O(1) |
|
|
356
|
+
| `isEmpty()` | 是否為空 | O(1) | O(1) |
|
|
357
|
+
| `findAny()` | 查找任意元素 | O(n) | O(1) |
|
|
358
|
+
| `findFirst()` | 查找第一個元素 | O(n) | O(1) |
|
|
359
|
+
| `findLast()` | 查找最後一個元素 | O(n) | O(1) |
|
|
360
|
+
| `forEach(action)` | 遍歷所有元素 | O(n) | O(1) |
|
|
361
|
+
| `group(classifier)` | 按分類器分組 | O(n) | O(n) |
|
|
362
|
+
| `groupBy(keyExtractor, valueExtractor)` | 按鍵值提取器分組 | O(n) | O(n) |
|
|
363
|
+
| `join()` | 連接為字串 | O(n) | O(n) |
|
|
364
|
+
| `join(delimiter)` | 使用分隔符連接 | O(n) | O(n) |
|
|
365
|
+
| `nonMatch(predicate)` | 是否沒有元素匹配 | O(n) | O(1) |
|
|
366
|
+
| `partition(count)` | 按數量分區 | O(n) | O(n) |
|
|
367
|
+
| `partitionBy(classifier)` | 按分類器分區 | O(n) | O(n) |
|
|
368
|
+
| `reduce(accumulator)` | 歸約操作 | O(n) | O(1) |
|
|
369
|
+
| `reduce(identity, accumulator)` | 帶初始值的歸約 | O(n) | O(1) |
|
|
370
|
+
| `toArray()` | 轉換為陣列 | O(n) | O(n) |
|
|
371
|
+
| `toMap(keyExtractor, valueExtractor)` | 轉換為Map | O(n) | O(n) |
|
|
372
|
+
| `toSet()` | 轉換為Set | O(n) | O(n) |
|
|
373
|
+
| `write(stream)` | 寫入流 | O(n) | O(1) |
|
|
374
|
+
|
|
302
375
|
```typescript
|
|
303
|
-
|
|
376
|
+
// Collectable 操作示例
|
|
377
|
+
const data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
378
|
+
.filter(n => n % 2 === 0)
|
|
379
|
+
.toOrdered();
|
|
304
380
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
{ name: "Charlie", age: 25, city: "New York" }
|
|
309
|
-
]);
|
|
381
|
+
// 匹配檢查
|
|
382
|
+
console.log(data.anyMatch(n => n > 5)); // true
|
|
383
|
+
console.log(data.allMatch(n => n < 20)); // true
|
|
310
384
|
|
|
311
|
-
//
|
|
312
|
-
|
|
385
|
+
// 查找操作
|
|
386
|
+
data.findFirst().ifPresent(n => console.log(n)); // 2
|
|
387
|
+
data.findAny().ifPresent(n => console.log(n)); // 任意元素
|
|
313
388
|
|
|
314
389
|
// 分組操作
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const byAge = collectable.groupBy(
|
|
319
|
-
person => person.age,
|
|
320
|
-
person => person.name
|
|
390
|
+
const grouped = data.groupBy(
|
|
391
|
+
n => n > 5 ? "large" : "small",
|
|
392
|
+
n => n * 2
|
|
321
393
|
);
|
|
322
|
-
//
|
|
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 }
|
|
394
|
+
// {small: [4, 8], large: [12, 16, 20]}
|
|
331
395
|
|
|
332
396
|
// 歸約操作
|
|
333
|
-
const
|
|
334
|
-
const oldest = collectable.reduce((a, b) => a.age > b.age ? a : b); // Optional.of({name: "Bob", age: 30, ...})
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### 特定收集器實作
|
|
397
|
+
const sum = data.reduce(0, (acc, n) => acc + n); // 30
|
|
338
398
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
- **方法**:繼承所有 Collectable 方法
|
|
343
|
-
|
|
344
|
-
#### OrderedCollectable<E>
|
|
345
|
-
- **特性**:保證元素順序,效能較低
|
|
346
|
-
- **使用場景**:需要排序結果
|
|
347
|
-
- **特殊方法**:繼承所有方法,維持內部排序狀態
|
|
399
|
+
// 輸出操作
|
|
400
|
+
data.join(", "); // "2, 4, 6, 8, 10"
|
|
401
|
+
```
|
|
348
402
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
403
|
+
## 統計分析方法
|
|
404
|
+
|
|
405
|
+
### NumericStatistics 方法
|
|
406
|
+
|
|
407
|
+
| 方法 | 描述 | 時間複雜度 | 空間複雜度 |
|
|
408
|
+
|------|------|------------|------------|
|
|
409
|
+
| `range()` | 極差 | O(n) | O(1) |
|
|
410
|
+
| `variance()` | 方差 | O(n) | O(1) |
|
|
411
|
+
| `standardDeviation()` | 標準差 | O(n) | O(1) |
|
|
412
|
+
| `mean()` | 平均值 | O(n) | O(1) |
|
|
413
|
+
| `median()` | 中位數 | O(n log n) | O(n) |
|
|
414
|
+
| `mode()` | 眾數 | O(n) | O(n) |
|
|
415
|
+
| `frequency()` | 頻率分佈 | O(n) | O(n) |
|
|
416
|
+
| `summate()` | 求和 | O(n) | O(1) |
|
|
417
|
+
| `quantile(quantile)` | 分位數 | O(n log n) | O(n) |
|
|
418
|
+
| `interquartileRange()` | 四分位距 | O(n log n) | O(n) |
|
|
419
|
+
| `skewness()` | 偏度 | O(n) | O(1) |
|
|
420
|
+
| `kurtosis()` | 峰度 | O(n) | O(1) |
|
|
355
421
|
|
|
356
|
-
**程式碼範例補充:**
|
|
357
422
|
```typescript
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
//
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
const
|
|
423
|
+
// 統計分析示例
|
|
424
|
+
const numbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
425
|
+
.toNumericStatistics();
|
|
426
|
+
|
|
427
|
+
console.log("平均值:", numbers.mean()); // 5.5
|
|
428
|
+
console.log("中位數:", numbers.median()); // 5.5
|
|
429
|
+
console.log("標準差:", numbers.standardDeviation()); // ~2.87
|
|
430
|
+
console.log("總和:", numbers.summate()); // 55
|
|
431
|
+
|
|
432
|
+
// 使用映射器的統計分析
|
|
433
|
+
const objects = from([
|
|
434
|
+
{ value: 10 },
|
|
435
|
+
{ value: 20 },
|
|
436
|
+
{ value: 30 }
|
|
437
|
+
]).toNumericStatistics();
|
|
438
|
+
|
|
439
|
+
console.log("映射平均值:", objects.mean(obj => obj.value)); // 20
|
|
440
|
+
```
|
|
369
441
|
|
|
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], ...
|
|
442
|
+
## 效能選擇指南
|
|
374
443
|
|
|
375
|
-
|
|
376
|
-
|
|
444
|
+
### 選擇無序收集器(效能優先)
|
|
445
|
+
```typescript
|
|
446
|
+
// 當不需要順序保證時,使用無序收集器獲得最佳效能
|
|
447
|
+
const highPerformance = data
|
|
448
|
+
.filter(predicate)
|
|
449
|
+
.map(mapper)
|
|
450
|
+
.toUnoredered(); // 最佳效能
|
|
377
451
|
```
|
|
378
452
|
|
|
379
|
-
###
|
|
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
|
-
**程式碼範例補充:**
|
|
453
|
+
### 選擇有序收集器(需要順序)
|
|
403
454
|
```typescript
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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, ...}
|
|
455
|
+
// 當需要保持元素順序時,使用有序收集器
|
|
456
|
+
const ordered = data
|
|
457
|
+
.sorted(comparator) // 排序操作會覆蓋重定向效果
|
|
430
458
|
```
|
|
431
459
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
**NumericStatistics<E>**
|
|
435
|
-
- 處理 number 型別的統計分析
|
|
436
|
-
- 所有統計計算回傳 number 型別
|
|
437
|
-
|
|
438
|
-
**BigIntStatistics<E>**
|
|
439
|
-
- 處理 bigint 型別的統計分析
|
|
440
|
-
- 所有統計計算回傳 bigint 型別
|
|
441
|
-
|
|
442
|
-
**程式碼範例補充:**
|
|
460
|
+
### 選擇視窗收集器(視窗操作)
|
|
443
461
|
```typescript
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const numericStats = numberData.toNumericStatistics();
|
|
449
|
-
|
|
450
|
-
console.log(numericStats.mean()); // 30
|
|
451
|
-
console.log(numericStats.summate()); // 150
|
|
452
|
-
|
|
453
|
-
// 大整數統計
|
|
454
|
-
const bigintData = from([100n, 200n, 300n, 400n, 500n]);
|
|
455
|
-
const bigintStats = bigintData.toBigIntStatistics();
|
|
456
|
-
|
|
457
|
-
console.log(bigintStats.mean()); // 300n
|
|
458
|
-
console.log(bigintStats.summate()); // 1500n
|
|
459
|
-
|
|
460
|
-
// 使用對映函數的統計
|
|
461
|
-
const objectData = from([
|
|
462
|
-
{ value: 15 },
|
|
463
|
-
{ value: 25 },
|
|
464
|
-
{ value: 35 },
|
|
465
|
-
{ value: 45 }
|
|
466
|
-
]);
|
|
467
|
-
|
|
468
|
-
const objectStats = objectData.toNumericStatistics();
|
|
469
|
-
const meanWithMapper = objectStats.mean(obj => obj.value); // 30
|
|
470
|
-
const sumWithMapper = objectStats.summate(obj => obj.value); // 120
|
|
462
|
+
// 需要進行視窗操作時
|
|
463
|
+
const windowed = data
|
|
464
|
+
.toWindow()
|
|
465
|
+
.slide(5n, 2n); // 滑動視窗
|
|
471
466
|
```
|
|
472
467
|
|
|
473
|
-
|
|
474
|
-
|
|
468
|
+
### 選擇統計分析(數值計算)
|
|
475
469
|
```typescript
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
//
|
|
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();
|
|
470
|
+
// 需要進行統計分析時
|
|
471
|
+
const stats = data
|
|
472
|
+
.toNumericStatistics(); // 數值統計
|
|
490
473
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
.filter(x => x > 5) // 再次過濾
|
|
495
|
-
.toArray(); // 轉換為陣列
|
|
496
|
-
|
|
497
|
-
console.log("處理結果:", results); // [16, 18, 14, 8, 12]
|
|
474
|
+
const bigIntStats = data
|
|
475
|
+
.toBigintStatistics(); // 大數統計
|
|
476
|
+
```
|
|
498
477
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
console.log("平均值:", stats.mean()); // 11.2
|
|
502
|
-
console.log("總和:", stats.summate()); // 56
|
|
503
|
-
}
|
|
478
|
+
[GitHub](https://github.com/eloyhere/semantic-typescript)
|
|
479
|
+
[NPMJS](https://www.npmjs.com/package/semantic-typescript)
|
|
504
480
|
|
|
505
|
-
|
|
506
|
-
const potentiallyInvalidData: Array<number | null> = [1, null, 3, 4, null];
|
|
507
|
-
const validData = potentiallyInvalidData.filter(validate);
|
|
508
|
-
const invalidData = potentiallyInvalidData.filter(invalidate);
|
|
481
|
+
## 注意事項
|
|
509
482
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
483
|
+
1. **排序操作的影響**:在有序收集器中,`sorted()` 操作會覆蓋 `redirect`、`translate`、`shuffle`、`reverse` 的效果
|
|
484
|
+
2. **效能考慮**:如果不需要順序保證,優先使用 `toUnoredered()` 獲得更好效能
|
|
485
|
+
3. **記憶體使用**:排序操作需要 O(n) 的額外空間
|
|
486
|
+
4. **實時數據**:Semantic 流適合處理實時數據,支援非同步數據源
|
|
513
487
|
|
|
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
|
-
這種設計確保了型別安全性和效能最佳化,同時提供豐富的串流處理功能。
|
|
488
|
+
這個庫為 TypeScript 開發者提供了強大而靈活的流式處理能力,結合了函數式編程的優點和類型安全的保障。
|