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/readme.tw.md CHANGED
@@ -1,335 +1,529 @@
1
- # 📘 semantic-typescript
1
+ # Semantic-TypeScript 串流處理框架
2
2
 
3
- 一個強大且**類型安全**的 TypeScript 工具庫,專為**語意化資料處理(Semantic Data Processing)**而設計。
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
- - 全面採用**類型安全的泛型(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
- ## 📦 安裝方式
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
- | `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()` |
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 { Optional } from 'semantic-typescript';
51
+ import { from, range, fill, empty } from 'semantic-typescript';
57
52
 
58
- const value: number | null = Math.random() > 0.5 ? 10 : null;
53
+ // 從陣列建立串流
54
+ const numberStream = from([1, 2, 3, 4, 5]);
59
55
 
60
- const opt = Optional.ofNullable(value);
56
+ // 建立數值範圍串流
57
+ const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
61
58
 
62
- const result = opt
63
- .filter(v => v > 5)
64
- .map(v => v * 2)
65
- .getOrDefault(0);
59
+ // 填充重複元素
60
+ const filledStream = fill("hello", 3n); // "hello", "hello", "hello"
66
61
 
67
- console.log(result); // 20 或 0
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
- 您可使用 `from()`、`range()`、`iterate()` `fill()` 等輔助函數建立 `Semantic` 資料流。
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
- | `from(iterable)` | 從陣列、集合或可迭代物件建立 | `from([1, 2, 3])` |
83
- | `range(start, end, step?)` | 產生數字範圍 | `range(0, 5)` → 0,1,2,3,4 |
84
- | `fill(element, count)` | 重複某個元素 N 次 | `fill('a', 3n)` |
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
- ```typescript
112
- const fastest = semanticStream.toUnordered();
93
+ // 產生隨機數
94
+ const randomNum = useRandom(42); // 基於種子 42 的隨機數
113
95
  ```
114
96
 
115
- 🔥 **不會套用任何排序演算法。**
116
- 當資料的順序不重要,而您追求極致效能時,這是最佳選擇。
97
+ ## 核心類別詳情
117
98
 
118
- ---
99
+ ### Optional<T> - 安全空值處理
119
100
 
120
- ### 4. `toOrdered()` `sorted()` — 排序後的資料
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
- const ordered = semanticStream.sorted(); // 自然排序
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
- ### 5. `Collector<E, A, R>` — 資料聚合
129
+ console.log(result); // "HELLO" "default"
135
130
 
136
- Collector 可讓您將資料流**縮減為單一值或複雜的資料結構**。
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
- Collector.full(identity, accumulator, finisher)
142
- Collector.shortable(identity, interruptor, accumulator, finisher)
143
- ```
174
+ import { from } from 'semantic-typescript';
144
175
 
145
- 但您通常會透過 `Collectable` 類別提供的高階方法來使用它們。
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
- ### 6. `Collectable<E>`(抽象類別)
186
+ // 注意:串流尚未執行,需要轉換為 Collectable 以進行終端操作
187
+ ```
150
188
 
151
- 以下類別的基礎:
189
+ #### 串流終端操作
152
190
 
153
- - `OrderedCollectable<E>` 排序後的資料
154
- - `UnorderedCollectable<E>` — 不排序,速度最快
155
- - `WindowCollectable<E>` 滑動視窗資料
156
- - `Statistics<E, D>` 統計資料聚合
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
- ### 7. `OrderedCollectable<E>` — 排序資料
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
- ```typescript
180
- const sorted = new OrderedCollectable(stream);
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
- ### 8. `UnorderedCollectable<E>` — 不排序(🚀 最快)
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
- const unordered = new UnorderedCollectable(stream);
194
- // 或
195
- const fastest = semanticStream.toUnordered();
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
- ### 9. `Statistics<E, D>` — 統計分析
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
- - `NumericStatistics<E>` 適用於 `number` 類型
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
- | `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
- ## 🧪 完整範例
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, toUnordered, toOrdered, sorted, NumericStatistics } from 'semantic-typescript';
234
-
235
- // 範例資料
236
- const numbers = from([10, 2, 8, 4, 5, 6]);
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());
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
- 本套件也提供多種**型別守衛(Type Guards)**與**比較工具**:
344
+ #### OrderedCollectable<E>
345
+ - **特性**:保證元素順序,效能較低
346
+ - **使用場景**:需要排序結果
347
+ - **特殊方法**:繼承所有方法,維持內部排序狀態
260
348
 
261
- | 函數 | 用途 |
262
- |------|------|
263
- | `isString(x)` | 判斷是否為 `string` |
264
- | `isNumber(x)` | 判斷是否為 `number` |
265
- | `isBoolean(x)` | 判斷是否為 `boolean` |
266
- | `isIterable(x)` | 判斷是否為可迭代物件 |
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
- ```typescript
277
- const gen = (accept: BiConsumer<number, bigint>, interrupt: Predicate<number>) => {
278
- for (let i = 0; i < 10; i++) {
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
- 或者使用**滑動視窗(Sliding Window)**:
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
- ```typescript
290
- const windowed = ordered.slide(3n, 2n); // 視窗大小為 3,每次移動 2
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
- 本專案採用 **MIT 授權**,可免費用於商業或個人用途。
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
- 歡迎提交 Pull Request、提出問題(Issues)或分享想法!
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
- - 📦 npm: https://www.npmjs.com/package/semantic-typescript
324
- - 🐙 GitHub: https://github.com/eloyhere/semantic-typescript
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
- **享受在 TypeScript 中進行函數式、類型安全且可組合的資料處理吧!** 🚀
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
- - `toUnordered()` → **不排序,最快**
335
- - 其他方法(如 `sorted()`、`toOrdered()`)→ **會進行排序**
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
+ 這種設計確保了型別安全性和效能最佳化,同時提供豐富的串流處理功能。