semantic-typescript 0.5.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/asynchronous/collector.d.ts +231 -0
  2. package/dist/asynchronous/collector.js +800 -0
  3. package/dist/asynchronous/semantic.d.ts +257 -0
  4. package/dist/asynchronous/semantic.js +1853 -0
  5. package/dist/factory.d.ts +71 -37
  6. package/dist/factory.js +443 -262
  7. package/dist/guard.d.ts +24 -14
  8. package/dist/guard.js +73 -19
  9. package/dist/hook.d.ts +6 -6
  10. package/dist/hook.js +2 -2
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +2 -2
  13. package/dist/optional.d.ts +2 -2
  14. package/dist/symbol.d.ts +19 -10
  15. package/dist/symbol.js +19 -10
  16. package/dist/synchronous/collector.d.ts +232 -0
  17. package/dist/{collector.js → synchronous/collector.js} +160 -151
  18. package/dist/{semantic.d.ts → synchronous/semantic.d.ts} +111 -120
  19. package/dist/{semantic.js → synchronous/semantic.js} +299 -337
  20. package/dist/utility.d.ts +7 -1
  21. package/dist/utility.js +1 -0
  22. package/package.json +1 -1
  23. package/readme.cn.md +158 -697
  24. package/readme.de.md +163 -432
  25. package/readme.es.md +163 -433
  26. package/readme.fr.md +162 -444
  27. package/readme.jp.md +162 -442
  28. package/readme.kr.md +161 -430
  29. package/readme.md +157 -1009
  30. package/readme.ru.md +161 -426
  31. package/readme.tw.md +161 -436
  32. package/dist/collector.d.ts +0 -236
  33. package/dist/main.d.ts +0 -1
  34. package/dist/main.js +0 -4
  35. package/dist/map.d.ts +0 -76
  36. package/dist/map.js +0 -245
  37. package/dist/node.d.ts +0 -182
  38. package/dist/node.js +0 -918
  39. package/dist/set.d.ts +0 -19
  40. package/dist/set.js +0 -65
  41. package/dist/tree.d.ts +0 -82
  42. package/dist/tree.js +0 -257
package/readme.tw.md CHANGED
@@ -1,489 +1,214 @@
1
- # Semantic-TypeScript 流處理庫
1
+ # Semantic-TypeScript:一款範式轉換的串流處理函式庫
2
2
 
3
3
  ## 簡介
4
+ Semantic-TypeScript 代表了串流處理技術的一項重大進步,它綜合了 JavaScript GeneratorFunctions、Java Streams 和資料庫索引範式中最有效的概念。其基礎設計原則的核心是透過複雜的惰性求值和智慧索引建構極其高效的資料處理管道。該函式庫提供了一個嚴格型別安全、函數式純正的串流式操作體驗,專門為現代 TypeScript 和 JavaScript 開發而設計。
4
5
 
5
- Semantic-TypeScript 是一個現代化的流處理庫,受到 JavaScript GeneratorFunction、Java Stream 和 MySQL Index 的啟發。它的核心設計哲學是基於數據索引來構建高效的數據處理管道,為前端開發提供類型安全、函數式風格的流式操作體驗。
6
+ 與傳統的同步處理架構相比,Semantic-TypeScript 實現了一個統一模型,優雅地處理同步(Iterable)和非同步(AsyncIterable)資料來源。在串流生成過程中,資料的流動和終止由回呼機制精確控制,使函式庫能夠以超凡的優雅處理:
6
7
 
7
- 與傳統的同步處理不同,Semantic 使用異步處理模型。在創建數據流時,終端接收數據的時間完全取決於上游何時調用 `accept` 和 `interrupt` 回調函數。這種設計使得庫能夠優雅地處理實時數據流、大數據集和異步數據源。
8
+ - 具有確定性控制的即時資料流(DOM 事件、WebSockets、時間間隔)
9
+ - 透過記憶體高效的惰性管道處理大規模資料集
10
+ - 透過流暢、宣告式的 API 進行複雜的資料轉換
8
11
 
9
- ## 安裝
12
+ 該函式庫的創新方法從根本上重新構想了開發者與資料序列互動的方式,在一個單一、內聚的套件中同時提供了前所未有的效能特性和開發者體驗。
10
13
 
11
- ```bash
12
- npm install semantic-typescript
13
- ```
14
+ ## 核心理念:定義與執行的分離
15
+ Semantic-TypeScript 的一個關鍵架構洞見是清晰地分離串流的定義和執行:
14
16
 
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` 類的 Symbol 標識符 |
25
- | `SemanticSymbol` | `Semantic` 類的 Symbol 標識符 |
26
- | `CollectorsSymbol` | `Collector` 類的 Symbol 標識符 |
27
- | `CollectableSymbol` | `Collectable` 類的 Symbol 標識符 |
28
- | `OrderedCollectableSymbol` | `OrderedCollectable` 類的 Symbol 標識符 |
29
- | `WindowCollectableSymbol` | `WindowCollectable` 類的 Symbol 標識符 |
30
- | `StatisticsSymbol` | `Statistics` 類的 Symbol 標識符 |
31
- | `NumericStatisticsSymbol` | `NumericStatistics` 類的 Symbol 標識符 |
32
- | `BigIntStatisticsSymbol` | `BigIntStatistics` 類的 Symbol 標識符 |
33
- | `UnorderedCollectableSymbol` | `UnorderedCollectable` 類的 Symbol 標識符 |
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>` | 生成器函數(核心與基礎) |
17
+ - **Semantic<E>**:一個不可變的、惰性的資料轉換管道藍圖。它定義了將執行哪些操作(過濾、映射等)
18
+ - **Collectable<E>**:一個已實例化的、可執行的串流視圖。它是從 Semantic 獲取的,並提供所有終端操作(收集、遍歷等)來執行管道並產生結果
52
19
 
53
- ```typescript
54
- // 類型使用範例
55
- let predicate: Predicate<number> = (n: number): boolean => n > 0;
56
- let mapper: Functional<string, number> = (text: string): number => text.length;
57
- let comparator: Comparator<number> = (a: number, b: number): number => a - b;
58
- ```
20
+ 這種分離強化了清晰的心智模型,並釋放了強大的最佳化能力,例如選擇 UnorderedCollectable 來跳過不必要的排序以實現最大速度。
59
21
 
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) |
85
- | `isPromise(t: unknown): t is Promise<unknown>` | 檢查是否為 Promise 物件 | O(1) | O(1) |
86
- | `isAsync(t: unknown): t is AsyncFunction` | 檢查是否為 AsyncFunction | O(1) | O(1) |
22
+ ## 為什麼選擇 Semantic-TypeScript?
23
+ 為資料串流處理選擇合適的函式庫需要在效能、型別安全性和表達能力之間取得平衡。Semantic-TypeScript 的設計旨在所有這些維度上都表現出色。
87
24
 
88
- ```typescript
89
- // 類型守衛使用範例
90
- let value: unknown = "hello";
25
+ ### 1. 適用於所有資料序列的統一、型別安全範式
26
+ 它為處理任何資料序列(無論是靜態陣列、即時事件還是非同步區塊)提供了一致的宣告式 API,同時利用 TypeScript 的全部功能確保端到端的型別安全。這消除了一整類執行時錯誤,並將串流操作轉變為可預測的、經過編譯器驗證的活動。
91
27
 
92
- if (isString(value)) {
93
- console.log(value.length); // 類型安全,value 被推斷為字串
94
- }
28
+ ### 2. 以智慧惰性求值實現的不妥協效能
29
+ 該函式庫的核心建立在惰性求值之上。諸如過濾器、映射和扁平映射等操作僅僅是組合一個處理管道;直到呼叫終端操作時,實際工作才會執行。這結合了短路功能(透過限制、任何匹配或自訂中斷回呼),允許處理提前停止,從而極大地提高了大型或無限串流的處理效率。
95
30
 
96
- if (isOptional(someValue)) {
97
- someValue.ifPresent((value): void => console.log(val));
98
- }
31
+ ### 3. `Collector<E, A, R>` 模式的強大之處
32
+ Java 啟發,收集器模式是靈活性的引擎。它將如何累積串流元素的規範與串流本身的執行解耦。該函式庫為日常任務提供了一組豐富的內建收集器(toArray、groupBy、summate 等),同時使實現您自己複雜的、可重用的歸約邏輯變得非常簡單。這比固定的一組終端方法要強大和可組合得多。
99
33
 
100
- if(isIterable(value)){
101
- // 類型安全,現在它是可迭代物件
102
- for(let item of value){
103
- console.log(item);
104
- }
105
- }
106
- ```
34
+ ### 4. 對現代 Web 和非同步資料的一流支援
35
+ Semantic-TypeScript 專為當代開發而設計。它為現代網路來源提供了原生工廠方法:
107
36
 
108
- ## 工具函數
37
+ - `useFrom(iterable)`, `useRange()` 用於靜態資料
38
+ - `useInterval()`, `useAnimationFrame()` 用於基於時間的串流
39
+ - `useBlob()` 用於分塊二進位資料處理
40
+ - `useWebSocket()`, `useDocument()`, `useWindow()` 用於即時事件流
109
41
 
110
- | 函數 | 描述 | 時間複雜度 | 空間複雜度 |
111
- |------|------|------------|------------|
112
- | `useCompare<T>(t1: T, t2: T): number` | 泛型比較函數 | O(1) | O(1) |
113
- | `useRandom<T = number \| bigint>(index: T): T` | 偽隨機數產生器 | O(log n) | O(1) |
42
+ ### 5. 超越基本聚合:內建統計分析
43
+ 超越簡單的求和與平均。該函式庫提供了專用的 NumericStatistics 和 BigIntStatistics 介面,可以直接從您的串流中即時存取進階統計指標——變異數、標準差、中位數、偏度和峰度。這將複雜的資料分析變成了一行程式碼。
114
44
 
115
- ```typescript
116
- // 工具函數使用範例
117
- let numbers: Array<number> = [3, 1, 4, 1, 5];
118
- numbers.sort(useCompare); // [1, 1, 3, 4, 5]
45
+ ### 6. 為開發者體驗而設計
46
+ - **流暢、可鏈式呼叫的 API**:將複雜的資料管道編寫為可讀的、順序鏈
47
+ - **全面的工具套件**:包含必要的守衛(isFunction, isIterable)、實用程式(useCompare, useTraverse)和函數式介面
48
+ - **Optional<T> 整合**:安全地建模值的缺失,消除了空指標的擔憂
49
+ - **效能指南**:清楚地指導何時使用無序集合以獲得速度,何時使用有序集合以保持序列
119
50
 
120
- let randomNum = useRandom(42); // 基於種子的隨機數
51
+ ## 安裝
52
+ ```bash
53
+ npm install semantic-typescript
121
54
  ```
122
55
 
123
- ## 工廠方法
56
+ ## 核心概念實踐
124
57
 
125
- ### Optional 工廠方法
126
-
127
- | 方法 | 描述 | 時間複雜度 | 空間複雜度 |
128
- |------|------|------------|------------|
129
- | `Optional.empty<T>()` | 建立一個空的 Optional | O(1) | O(1) |
130
- | `Optional.of<T>(value)` | 建立一個包含值的 Optional | O(1) | O(1) |
131
- | `Optional.ofNullable<T>(value)` | 建立一個可能為空的 Optional | O(1) | O(1) |
132
- | `Optional.ofNonNull<T>(value)` | 建立一個非空的 Optional | O(1) | O(1) |
58
+ ### 1. 建立串流 (Semantic)
59
+ 可以使用工廠函數從各種來源建立串流。
133
60
 
134
61
  ```typescript
135
- // Optional 使用範例
136
- let empty: Optional<number> = Optional.empty();
137
- let present: Optional<number> = Optional.of(42);
138
- let nullable: Optional<string> = Optional.ofNullable<string>(null);
139
- let nonNull: Optional<string> = Optional.ofNonNull("hello");
140
-
141
- presentO.ifPresent((value: number): void => console.log(value)); // 輸出 42
142
- console.log(empty.get(100)); // 輸出 100
143
- ```
144
-
145
- ### Collector 工廠方法
146
-
147
- | 方法 | 描述 | 時間複雜度 | 空間複雜度 |
148
- |------|------|------------|------------|
149
- | `Collector.full(identity, accumulator, finisher)` | 建立一個完整的收集器 | O(1) | O(1) |
150
- | `Collector.shortable(identity, interruptor, accumulator, finisher)` | 建立一個可中斷的收集器 | O(1) | O(1) |
62
+ import { useFrom, useInterval, useDocument } from 'semantic-typescript';
151
63
 
152
- ```typescript
153
- // Collector 轉換範例
154
- let numbers: Semantic<number> = from([3, 1, 4, 1, 5, 9, 2, 6, 5]);
155
-
156
- // 效能優先:使用無序收集器
157
- let unordered: UnorderedCollectable<number> = from([3, 1, 4, 1, 5, 9, 2, 6, 5])
158
- .filter((n: number): boolean => n > 3)
159
- .toUnordered();
160
-
161
- // 需要排序:使用有序收集器
162
- let ordered: OrderedCollectable<number> = from([3, 1, 4, 1, 5, 9, 2, 6, 5])
163
- .sorted();
164
-
165
- // 統計元素數量
166
- let count: Collector<number, number, number> = Collector.full(
167
- (): number => 0, // 初始值
168
- (accumulator: number, element: number): number => accumulator + element, // 累積
169
- (accumulator: number): number => accumulator // 完成
170
- );
171
- count.collect(from([1,2,3,4,5])); // 從流中統計
172
- count.collect([1,2,3,4,5]); // 從可迭代物件統計
173
-
174
- let find: Optional<number> = Collector.shortable(
175
- (): Optional<number> => Optional.empty(), // 初始值
176
- (element: number, index: bigint, accumulator: Optional<number>): Optional<number> => accumulator.isPresent(), // 中斷
177
- (accumulator: Optional<number>, element: number, index: bigint): Optional<number> => Optional.of(element), // 累積
178
- (accumulator: Optional<number>): Optional<number> => accumulator // 完成
179
- );
180
- find.collect(from([1,2,3,4,5])); // 查找第一個元素
181
- find.collect([1,2,3,4,5]); // 查找第一個元素
182
- ```
64
+ // 從靜態陣列建立
65
+ const staticStream = useFrom([1, 2, 3, 4, 5]);
183
66
 
184
- ### Semantic 工廠方法
67
+ // 從非同步產生器建立
68
+ const asyncStream = useFrom(async function*() {
69
+ yield 1;
70
+ yield 2;
71
+ });
185
72
 
186
- | 方法 | 描述 | 時間複雜度 | 空間複雜度 |
187
- |------|------|------------|------------|
188
- | `animationFrame(period: number, delay: number = 0)` | 建立定時動畫幀流 | O(1)* | O(1) |
189
- | `blob(blob, chunkSize)` | 從 Blob 建立流 | O(n) | O(chunkSize) |
190
- | `empty<E>()` | 建立空流 | O(1) | O(1) |
191
- | `fill<E>(element, count)` | 建立填充流 | O(n) | O(1) |
192
- | `from<E>(iterable)` | 從可迭代物件建立流 | O(1) | O(1) |
193
- | `interval(period, delay?)` | 建立定時間隔流 | O(1)* | O(1) |
194
- | `iterate<E>(generator)` | 從生成器建立流 | O(1) | O(1) |
195
- | `range(start, end, step)` | 建立數值範圍流 | O(n) | O(1) |
196
- | `websocket(websocket)` | 從 WebSocket 建立流 | O(1) | O(1) |
73
+ // 一個基於時間的串流
74
+ const tickStream = useInterval(1000); // 每秒發射一次
197
75
 
198
- ```typescript
199
- // Semantic 工廠方法使用範例
200
-
201
- // 從定時動畫幀建立流
202
- animationFrame(1000)
203
- .toUnordered()
204
- .forEach(frame => console.log(frame));
205
-
206
- // 從 Blob 建立流(分塊讀取)
207
- blob(someBlob, 1024n)
208
- .toUnordered()
209
- .write(WritableStream)
210
- .then(callback) // 寫入流成功
211
- .catch(callback); // 寫入流失敗
212
-
213
- // 建立空流,需與其他流連接後才會執行
214
- empty<string>()
215
- .toUnordered()
216
- .join(); //[]
217
-
218
- // 建立填充流
219
- let filledStream = fill("hello", 3); // "hello", "hello", "hello"
220
-
221
- // 建立初始延遲 2 秒、執行週期 5 秒的定時流,基於定時器機制實現;可能因系統排程精確度限制產生時間漂移。
222
- let intervalStream = interval(5000, 2000);
223
-
224
- // 從可迭代物件建立流
225
- let numberStream = from([1, 2, 3, 4, 5]);
226
- let stringStream = from(new Set(["Alex", "Bob"]));
227
-
228
- // 從已解析的 Promise 建立流
229
- let promisedStream: Semantic<Array<number>> = Promise.resolve([1, 2, 3, 4, 5]);
230
-
231
- // 建立範圍流
232
- let rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
233
-
234
- // WebSocket 事件流
235
- let ws = new WebSocket("ws://localhost:8080");
236
- websocket(ws)
237
- .filter((event): boolean => event.type === "message"); // 僅監聽訊息事件
238
- .toUnordered() // 事件通常無序
239
- .forEach((event): void => receive(event)); // 接收訊息
76
+ // 一個 DOM 事件流(參見下面的重要說明)
77
+ const clickStream = useDocument('click');
240
78
  ```
241
79
 
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) |
80
+ ### 2. 轉換串流(中間操作)
81
+ 透過鏈式惰性呼叫來定義管道。
267
82
 
268
83
  ```typescript
269
- // Semantic 操作範例
270
- let result = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
271
- .filter((n: number): boolean => n % 2 === 0) // 過濾偶數
272
- .map((n: number): number => n * 2) // 乘以 2
273
- .skip(1) // 跳過第一個
274
- .limit(3) // 限制為 3 個元素
275
- .toUnordered() // 轉換為無序收集器
276
- .toArray(); // 轉換為陣列
277
- // 結果: [8, 12, 20]
278
-
279
- // 複雜操作範例
280
- let complexResult = range(1, 100, 1)
281
- .flatMap((n: number): Semantics<number> => from([n, n * 2])) // 將每個元素映射為兩個
282
- .distinct() // 移除重複項
283
- .shuffle() // 隨機洗牌
284
- .takeWhile((n: number): boolean => n < 50) // 取小於 50 的元素
285
- .toOrdered() // 轉換為有序收集器
286
- .toArray(); // 轉換為陣列
287
- ```
288
-
289
- ## Semantic 轉換方法
290
-
291
- | 方法 | 描述 | 時間複雜度 | 空間複雜度 |
292
- |------------|------------|------------|------------|
293
- | `sorted()` | 轉換為有序收集器 | O(n log n) | O(n) |
294
- | `toUnordered()` | 轉換為無序收集器 | O(1) | O(1) |
295
- | `toOrdered()` | 轉換為有序收集器 | O(1) | O(1) |
296
- | `toNumericStatistics()` | 轉換為數值統計 | O(n) | O(1) |
297
- | `toBigintStatistics()` | 轉換為 BigInt 統計 | O(n) | O(1) |
298
- | `toWindow()` | 轉換為視窗收集器 | O(1) | O(1) |
299
- | `toCollectable()` | 轉換為 `UnorderdCollectable` | O(n) | O(1) |
300
- | `toCollectable(mapper)` | 轉換為自訂收集器 | O(n) | O(1) |
84
+ const processedStream = staticStream
85
+ .filter(x => x % 2 === 0) // 僅保留偶數
86
+ .map(x => x * 10) // 乘以 10
87
+ .flatMap(x => [x, x + 1]) // 將每個元素轉換為兩個
88
+ .distinct(); // 移除重複項
301
89
 
302
- ```typescript
303
- // 轉換為升序陣列
304
- from([6,4,3,5,2]) // 建立流
305
- .sorted() // 按升序排序
306
- .toArray(); // [2, 3, 4, 5, 6]
307
-
308
- // 轉換為降序陣列
309
- from([6,4,3,5,2]) // 建立流
310
- .soted((a: number, b: number): number => b - a) // 按降序排序
311
- .toArray(); // [6, 5, 4, 3, 2]
312
-
313
- // 重定向為倒序陣列
314
- from([6,4,3,5,2])
315
- .redirect((element, index): bigint => -index) // 重定向為倒序
316
- .toOrderd() // 保持重定向順序
317
- .toArray(); // [2, 5, 3, 4, 6]
318
-
319
- // 忽略重定向以倒序陣列
320
- from([6,4,3,5,2])
321
- .redirect((element: number, index: bigint) => -index) // 重定向為倒序
322
- .toUnorderd() // 丟棄重定向順序。此操作將忽略 `redirect`、`reverse`、`shuffle` 和 `translate` 操作
323
- .toArray(); // [2, 5, 3, 4, 6]
324
-
325
- // 反轉流為陣列
326
- from([6, 4, 3, 5, 2])
327
- .reverse() // 反轉流
328
- .toOrdered() // 保證反轉順序
329
- .toArray(); // [2, 5, 3, 4, 6]
330
-
331
- // 覆蓋洗牌的流為陣列
332
- from([6, 4, 3, 5, 2])
333
- .shuffle() // 洗牌流
334
- .sorted() // 覆蓋洗牌順序。此操作將覆蓋 `redirect`、`reverse`、`shuffle` 和 `translate` 操作
335
- .toArray(); // [2, 5, 3, 4, 6]
336
-
337
- // 轉換為視窗收集器
338
- from([6, 4, 3, 5, 2]).toWindow();
339
-
340
- // 轉換為數值統計
341
- from([6, 4, 3, 5, 2]).toNumericStatistics();
342
-
343
- // 轉換為 BigInt 統計
344
- from([6n, 4n, 3n, 5n, 2n]).toBigintStatistics();
345
-
346
- // 定義自訂收集器來收集資料
347
- let customizedCollector = from([1, 2, 3, 4, 5]).toCollectable((generator: Generator<E>) => new CustomizedCollector(generator));
90
+ // 此時尚未執行任何操作
348
91
  ```
349
92
 
350
- ## Collectable 集合方法
351
-
352
- | 方法 | 描述 | 時間複雜度 | 空間複雜度 |
353
- |------|------|------------|------------|
354
- | `anyMatch(predicate)` | 是否有任何元素符合 | O(n) | O(1) |
355
- | `allMatch(predicate)` | 是否所有元素都符合 | O(n) | O(1) |
356
- | `count()` | 元素計數 | O(n) | O(1) |
357
- | `isEmpty()` | 是否為空 | O(1) | O(1) |
358
- | `findAny()` | 查找任何元素 | O(n) | O(1) |
359
- | `findFirst()` | 查找第一個元素 | O(n) | O(1) |
360
- | `findLast()` | 查找最後一個元素 | O(n) | O(1) |
361
- | `forEach(action)` | 遍歷所有元素 | O(n) | O(1) |
362
- | `group(classifier)` | 按分類器分組 | O(n) | O(n) |
363
- | `groupBy(keyExtractor, valueExtractor)` | 按鍵值提取器分組 | O(n) | O(n) |
364
- | `join()` | 將元素連接為字串 | O(n) | O(n) |
365
- | `join(delimiter)` | 使用分隔符連接元素 | O(n) | O(n) |
366
- | `nonMatch(predicate)` | 是否沒有任何元素符合 | O(n) | O(1) |
367
- | `partition(count)` | 按計數分區 | O(n) | O(n) |
368
- | `partitionBy(classifier)` | 按分類器分區 | O(n) | O(n) |
369
- | `reduce(accumulator)` | 歸約操作 | O(n) | O(1) |
370
- | `reduce(identity, accumulator)` | 使用初始值的歸約操作 | O(n) | O(1) |
371
- | `toArray()` | 轉換為陣列 | O(n) | O(n) |
372
- | `toMap(keyExtractor, valueExtractor)` | 轉換為 Map | O(n) | O(n) |
373
- | `toSet()` | 轉換為 Set | O(n) | O(n) |
374
- | `write(stream)` | 寫入流 | O(n) | O(1) |
93
+ ### 3. 執行串流(終端操作)
94
+ 要獲得結果,必須取得一個 Collectable 並呼叫終端操作。
375
95
 
376
96
  ```typescript
377
- // Collectable 操作範例
378
- let data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
379
- .filter((n: number): boolean => n % 2 === 0)
380
- .toOrdered();
381
-
382
- // 符合檢查
383
- console.log(data.anyMatch((n: number): boolean => n > 5)); // true
384
- console.log(data.allMatch((n: number): boolean => n < 20)); // true
385
-
386
- // 查找操作
387
- data.findFirst().ifPresent((n: number): void => console.log(n)); // 2
388
- data.findAny().ifPresent((n: number): void => console.log(n)); // 任何元素
389
-
390
- // 分組操作
391
- let grouped = data.groupBy(
392
- (n: number): string => (n > 5 ? "large" : "small"),
393
- (n: number): number => n * 2
394
- ); // {small: [4, 8], large: [12, 16, 20]}
395
-
396
- // 歸約操作
397
- let sum = data.reduce(0, (accumulator: number, n: number): number => accumulator + n); // 30
398
-
399
- // 輸出操作
400
- data.join(", "); // "[2, 4, 6, 8, 10]"
97
+ // 取得一個無序收集器以提高效能
98
+ const resultArray = await processedStream.toUnordered().toArray();
99
+ console.log(resultArray); // 例如:[20, 21, 40, 41]
100
+
101
+ // 使用內建收集器
102
+ const sum = await processedStream.toUnordered().collect(useSummate());
103
+ console.log(sum);
104
+
105
+ // 或使用通用的 collect 方法
106
+ const customResult = await processedStream.toOrdered().collect(
107
+ () => new Map<number, number>(),
108
+ (map, element, index) => map.set(index, element),
109
+ map => map
110
+ );
401
111
  ```
402
112
 
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) |
113
+ ### 4. 關鍵:處理事件流
114
+ 事件流(useDocument, useWindow, useHTMLElement, useWebSocket)本質上是無限的。您必須使用諸如 sub、takeWhile 或 limit 等操作來定義何時停止收集事件並完成串流。否則,終端操作將無限期等待。
421
115
 
422
116
  ```typescript
423
- // 統計分析範例
424
- let 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
- let objects = from([
434
- { value: 10 },
435
- { value: 20 },
436
- { value: 30 }
437
- ]).toNumericStatistics();
438
- console.log("映射後的平均:", objects.mean(obj => obj.value)); // 20
117
+ import { useDocument } from 'semantic-typescript';
118
+
119
+ // 僅收集前 5 次點擊
120
+ const first5Clicks = await useDocument('click')
121
+ .limit(5) // <- 關鍵:將串流限制為 5 個事件
122
+ .toUnordered()
123
+ .toArray();
124
+
125
+ // 收集 10 秒視窗內的點擊
126
+ const clicksIn10s = await useDocument('click')
127
+ .takeWhile((_, index, startTime = Date.now()) => Date.now() - startTime < 10000)
128
+ .toUnordered()
129
+ .toArray();
130
+
131
+ // 收集索引 2 到 5 的點擊(基於 0)
132
+ const specificClicks = await useDocument('click')
133
+ .sub(2n, 6n) // <- 獲取索引為 2, 3, 4, 5 的元素
134
+ .toUnordered()
135
+ .toArray();
439
136
  ```
440
137
 
441
- ## 效能選擇指南
442
-
443
- ### 選擇無序收集器(效能優先)
138
+ **關鍵見解**:事件(例如 MouseEvent)及其順序觸發索引(作為大整數)透過 `accept(event, index)` 回呼一起在管道中傳遞。
444
139
 
140
+ ### 5. 利用統計功能
445
141
  ```typescript
446
- // 當不需要順序保證時,使用無序收集器以獲得最佳效能
447
- let highPerformance = data
448
- .filter(predicate)
449
- .map(mapper)
450
- .toUnordered(); // 最佳效能
451
- ```
142
+ const numericStream = useFrom([10, 20, 30, 40, 50]).toNumeric();
452
143
 
453
- ### 選擇有序收集器(需要順序)
144
+ const average = await numericStream.average();
145
+ const median = await numericStream.median();
146
+ const standardDeviation = await numericStream.standardDeviation();
147
+ const skewness = await numericStream.skewness();
454
148
 
455
- ```typescript
456
- // 當需要維持元素順序時,使用有序收集器
457
- let ordered = data.sorted(comparator);
149
+ console.log(`Average: ${average}, Median: ${median}, StdDev: ${standardDeviation}`);
458
150
  ```
459
151
 
460
- ### 選擇視窗收集器(視窗操作)
461
-
152
+ ## 主要特性
153
+ - **雙流類型**:完全支援同步語意(用於 Iterable)和非同步語意(用於 AsyncIterable 和事件)
154
+ - **豐富的操作集**:過濾器、映射、扁平映射、連接、去重、排序、限制、跳過、檢視、反轉、打亂
155
+ - **靈活的終端操作**:收集(使用自訂收集器)、toArray、toSet、toMap、forEach、reduce、findFirst、anyMatch、allMatch、count
156
+ - **進階收集器**:用於連接、分組、分割區、求和、平均、最大值、最小值的內建收集器
157
+ - **統計模組**:在數值/大整數流上用於均值、中位數、眾數、變異數、標準差、範圍、分位數、偏度、峰度的即用型方法
158
+ - **實用函數**:型別守衛(isPromise, isAsyncIterable)、比較器(useCompare)、遍歷(useTraverse)和轉換勾點
159
+ - **Optional<T>**:一個用於可空值的單子容器,與查詢操作整合
160
+
161
+ ## API 概述
162
+ ### 核心類別和介面
163
+ - `Semantic<E>` / `AsynchronousSemantic<E>`:抽象的串流定義
164
+ - `Collectable<E>` / `AsynchronousCollectable<E>`:具有終端操作的可執行串流
165
+ - `OrderedCollectable<E>` / `UnorderedCollectable<E>`:為順序敏感或順序不敏感操作最佳化的實例化版本
166
+ - `Collector<E, A, R>`:可變歸約操作的抽象
167
+
168
+ ### 工廠函數 (use*)
169
+ - **從來源建立**:useFrom, useRange, useFill, useEmpty
170
+ - **從時間建立**:useInterval, useAnimationFrame
171
+ - **從 Web API 建立**:useBlob, useDocument, useWindow, useHTMLElement, useWebSocket
172
+ - **收集器**:useToArray, useGroupBy, useSummate, useJoin 等
173
+
174
+ ## 效能說明
175
+ - **惰性求值**:在呼叫終端操作之前,管道僅組合而不執行
176
+ - **短路求值**:諸如限制、任何匹配和查詢首個等操作將在結果確定後立即停止處理元素
177
+ - **有序與無序**:
178
+ - 當來源元素的順序對您的結果不重要時(例如,求和、最大值或 toSet),對終端操作使用 `.toUnordered()`。這允許內部最佳化跳過昂貴的排序步驟
179
+ - 當順序很重要時(例如,toArray 必須保留順序),使用 `.toOrdered()`
180
+
181
+ ## 入門範例
462
182
  ```typescript
463
- // 當需要視窗操作時
464
- let window: WindowCollectable<number> = data
465
- .toWindow()
466
- .slide(5n, 2n); // 滑動視窗
467
- ```
183
+ import { useFrom, useSummate, useGroupBy } from 'semantic-typescript';
468
184
 
469
- ### 選擇統計分析(數值計算)
185
+ interface Transaction {
186
+ id: number;
187
+ amount: number;
188
+ category: string;
189
+ }
470
190
 
471
- ```typescript
472
- // 當需要統計分析時
473
- let statistics: NumericStatistics<number> = data
474
- .toNumericStatistics(); // 數值統計
475
- let bigIntStatistics: BigintStatistics<bigint> = data
476
- .toBigintStatistics(); // 大整數統計
191
+ const transactions: Transaction[] = [
192
+ { id: 1, amount: 100, category: 'Food' },
193
+ { id: 2, amount: 200, category: 'Electronics' },
194
+ { id: 3, amount: 50, category: 'Food' },
195
+ { id: 4, amount: 300, category: 'Electronics' },
196
+ ];
197
+
198
+ // 計算每個類別的總金額
199
+ const totalsByCategory = await useFrom(transactions)
200
+ .toUnordered()
201
+ .collect(
202
+ useGroupBy(
203
+ t => t.category,
204
+ t => t.amount,
205
+ useSummate() // 值的收集器
206
+ )
207
+ );
208
+
209
+ console.log(totalsByCategory); // Map { 'Food' => 150, 'Electronics' => 500 }
477
210
  ```
478
211
 
479
- [GitHub](https://github.com/eloyhere/semantic-typescript)
480
- [NPMJS](https://www.npmjs.com/package/semantic-typescript)
481
-
482
- ## 重要注意事項
483
-
484
- 1. **排序操作的影響**:在有序收集器中,`sorted()` 操作會覆蓋 `redirect`、`translate`、`shuffle`、`reverse` 的效果。
485
- 2. **效能考量**:如果不需要順序保證,優先使用 `toUnordered()` 以獲得更好的效能。
486
- 3. **記憶體使用**:排序操作需要額外的 O(n) 空間。
487
- 4. **即時資料**:Semantic 流適用於處理即時資料,並支援異步資料來源。
212
+ Semantic-TypeScript 是為那些尋求嚴格設計、型別安全和高效能串流處理函式庫的開發者而建構的。它將企業級資料轉換模式的力量帶入了 TypeScript 生態系統,非常適合資料密集型前端應用程式、Node.js 資料處理,以及任何需要優雅、高效處理序列的場景。
488
213
 
489
- 這個庫為 TypeScript 開發者提供了強大而靈活的流處理能力,結合了函數式程式設計的好處和類型安全的保證。
214
+ [![GitHub](./GitHub.png)](https://github.com/eloyhere/semantic-typescript) [![NPM](./NPM.png)](https://www.npmjs.com/package/semantic-typescript)