semantic-typescript 0.0.6 → 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.kr.md ADDED
@@ -0,0 +1,529 @@
1
+ # Semantic-TypeScript 스트림 처리 프레임워크
2
+
3
+ ## 소개
4
+
5
+ Semantic-TypeScript는 JavaScript GeneratorFunction, Java Stream 및 MySQL Index에서 영감을 받은 현대적인 스트림 처리 라이브러리입니다. 핵심 설계 철학은 데이터 인덱싱을 통해 효율적인 데이터 처리 파이프라인을 구축하는 데 있으며, 프론트엔드 개발을 위해 타입 안전적이고 함수형 스타일의 스트리밍 작업 경험을 제공합니다.
6
+
7
+ 기존의 동기식 처리와 달리 Semantic은 비동기 처리 모델을 채택합니다. 데이터 스트림을 생성할 때 최종 데이터 수신 시점은 전적으로 업스트림이 `accept` 및 `interrupt` 콜백 함수를 호출하는 시점에 따라 결정됩니다. 이 설계는 라이브러리가 실시간 데이터 스트림, 대용량 데이터 세트 및 비동기 데이터 소스를 우아하게 처리할 수 있게 합니다.
8
+
9
+ ## 핵심 기능
10
+
11
+ | 기능 | 설명 | 장점 |
12
+ |------|------|------|
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
+ **코드 예시 보충:**
50
+ ```typescript
51
+ import { from, range, fill, empty } from 'semantic-typescript';
52
+
53
+ // 배열로부터 스트림 생성
54
+ const numberStream = from([1, 2, 3, 4, 5]);
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>();
64
+ ```
65
+
66
+ ### 유틸리티 함수 팩토리
67
+
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
+ ```typescript
77
+ import { validate, invalidate, useCompare, useRandom } from 'semantic-typescript';
78
+
79
+ // 데이터 유효성 검증
80
+ const data: string | null = "hello";
81
+ if (validate(data)) {
82
+ console.log(data.toUpperCase()); // validate가 데이터가 null이 아님을 보장하므로 안전한 호출
83
+ }
84
+
85
+ const nullData: string | null = null;
86
+ if (invalidate(nullData)) {
87
+ console.log("데이터 무효"); // invalidate가 null을 감지했으므로 실행됨
88
+ }
89
+
90
+ // 값 비교
91
+ const comparison = useCompare("apple", "banana"); // -1
92
+
93
+ // 난수 생성
94
+ const randomNum = useRandom(42); // 시드 42 기반 난수
95
+ ```
96
+
97
+ ## 핵심 클래스 상세
98
+
99
+ ### Optional<T> - 안전한 Null 값 처리
100
+
101
+ Optional 클래스는 null 또는 undefined일 수 있는 값을 안전하게 처리하기 위한 함수형 접근 방식을 제공합니다.
102
+
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>` | nullable Optional 생성 | O(1) |
114
+ | `static ofNonNull<T>(value: T)` | `Optional<T>` | non-null Optional 생성 | O(1) |
115
+
116
+ **코드 예시 보충:**
117
+ ```typescript
118
+ import { Optional } from 'semantic-typescript';
119
+
120
+ // Optional 인스턴스 생성
121
+ const optionalValue = Optional.ofNullable<string>(Math.random() > 0.5 ? "hello" : null);
122
+
123
+ // 연쇄 연산
124
+ const result = optionalValue
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
+ }
142
+ ```
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
+ **코드 예시 보충:**
173
+ ```typescript
174
+ import { from } from 'semantic-typescript';
175
+
176
+ const stream = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
177
+
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(`인덱스 ${index}의 요소 ${val}`)); // 요소 확인
185
+
186
+ // 참고: 스트림은 아직 실행되지 않음, 터미널 연산을 위해 Collectable로 변환 필요
187
+ ```
188
+
189
+ #### 스트림 터미널 연산
190
+
191
+ | 메서드 | 반환 타입 | 설명 | 성능 특성 |
192
+ |------|----------|------|----------|
193
+ | `toOrdered()` | `OrderedCollectable<E>` | 정렬된 컬렉션으로 변환 | 정렬 연산, 낮은 성능 |
194
+ | `toUnordered()` | `UnorderedCollectable<E>` | 비정렬 컬렉션으로 변환 | 가장 빠름, 정렬 없음 |
195
+ | `toWindow()` | `WindowCollectable<E>` | 윈도우 컬렉션으로 변환 | 정렬 연산, 낮은 성능 |
196
+ | `toNumericStatistics()` | `Statistics<E, number>` | 숫자 통계 분석 | 정렬 연산, 낮은 성능 |
197
+ | `toBigintStatistics()` | `Statistics<E, bigint>` | Big integer 통계 분석 | 정렬 연산, 낮은 성능 |
198
+ | `sorted()` | `OrderedCollectable<E>` | 자연 정렬 | 재지정 결과 재정의 |
199
+ | `sorted(comparator)` | `OrderedCollectable<E>` | 사용자 정의 정렬 | 재지정 결과 재정의 |
200
+
201
+ **코드 예시 보충:**
202
+ ```typescript
203
+ import { from } from 'semantic-typescript';
204
+
205
+ const semanticStream = from([5, 2, 8, 1, 9, 3, 7, 4, 6]);
206
+
207
+ // 정렬된 컬렉션으로 변환 (낮은 성능)
208
+ const ordered = semanticStream.toOrdered();
209
+
210
+ // 비정렬 컬렉션으로 변환 (가장 빠름)
211
+ const unordered = semanticStream.toUnordered();
212
+
213
+ // 자연 정렬
214
+ const sortedNatural = semanticStream.sorted();
215
+
216
+ // 사용자 정의 정렬
217
+ const sortedCustom = semanticStream.sorted((a, b) => b - a); // 내림차순 정렬
218
+
219
+ // 통계 객체로 변환
220
+ const stats = semanticStream.toNumericStatistics();
221
+
222
+ // 참고: 위 메서드들은 Semantic 인스턴스를 통해 호출하여 Collectable을 얻은 후 터미널 메서드 사용 필요
223
+ ```
224
+
225
+ ### Collector<E, A, R> - 데이터 수집기
226
+
227
+ 수집기는 스트림 데이터를 특정 구조로 집계하는 데 사용됩니다.
228
+
229
+ | 메서드 | 설명 | 사용 시나리오 |
230
+ |------|------|----------|
231
+ | `collect(generator)` | 데이터 수집 실행 | 스트림 터미널 연산 |
232
+ | `static full(identity, accumulator, finisher)` | 완전한 수집기 생성 | 완전한 처리 필요 |
233
+ | `static shortable(identity, interruptor, accumulator, finisher)` | 중단 가능 수집기 생성 | 조기 종료 가능 |
234
+
235
+ **코드 예시 보충:**
236
+ ```typescript
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
249
+ ```
250
+
251
+ ### Collectable<E> - 수집 가능 데이터 추상 클래스
252
+
253
+ 풍부한 데이터 집계 및 변환 메서드를 제공합니다. **참고: 반드시 Semantic 인스턴스를 통해 sorted(), toOrdered() 등을 먼저 호출하여 Collectable 인스턴스를 얻은 후 다음 메서드들을 사용해야 합니다.**
254
+
255
+ #### 데이터 쿼리 연산
256
+
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>` |
266
+
267
+ **코드 예시 보충:**
268
+ ```typescript
269
+ import { from } from 'semantic-typescript';
270
+
271
+ const numbers = from([1, 2, 3, 4, 5]);
272
+
273
+ // 터미널 메서드 사용 전 반드시 Collectable로 변환
274
+ const collectable = numbers.toUnordered();
275
+
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
+ ```
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
+ **코드 예시 보충:**
302
+ ```typescript
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, ...})
335
+ ```
336
+
337
+ ### 특정 수집기 구현
338
+
339
+ #### UnorderedCollectable<E>
340
+ - **특징**: 가장 빠른 수집기, 정렬 없음
341
+ - **사용 시나리오**: 순서 중요하지 않음, 최대 성능 원할 때
342
+ - **메서드**: 모든 Collectable 메서드 상속
343
+
344
+ #### OrderedCollectable<E>
345
+ - **특징**: 요소 순서 보장, 낮은 성능
346
+ - **사용 시나리오**: 정렬된 결과 필요
347
+ - **특별 메서드**: 모든 메서드 상속, 내부 정렬 상태 유지
348
+
349
+ #### WindowCollectable<E>
350
+ - **특징**: 슬라이딩 윈도우 연산 지원
351
+ - **사용 시나리오**: 시계열 데이터 분석
352
+ - **특별 메서드**:
353
+ - `slide(size, step)` - 슬라이딩 윈도우
354
+ - `tumble(size)` - 텀블링 윈도우
355
+
356
+ **코드 예시 보충:**
357
+ ```typescript
358
+ import { from } from 'semantic-typescript';
359
+
360
+ const data = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
361
+
362
+ // 비정렬 수집기 (가장 빠름)
363
+ const unordered = data.toUnordered();
364
+ const unorderedArray = unordered.toArray(); // 원본 순서 유지 가능 [1, 2, 3, ...]
365
+
366
+ // 정렬 수집기
367
+ const ordered = data.toOrdered();
368
+ const orderedArray = ordered.toArray(); // 정렬 보장 [1, 2, 3, ...]
369
+
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], ...
374
+
375
+ const tumblingWindows = windowed.tumble(4n); // 텀블링 윈도우 크기 4
376
+ // 윈도우 1: [1, 2, 3, 4], 윈도우 2: [5, 6, 7, 8], ...
377
+ ```
378
+
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
+ ```
431
+
432
+ #### 특정 통계 구현 클래스
433
+
434
+ **NumericStatistics<E>**
435
+ - number 타입 통계 분석 처리
436
+ - 모든 통계 계산이 number 타입 반환
437
+
438
+ **BigIntStatistics<E>**
439
+ - bigint 타입 통계 분석 처리
440
+ - 모든 통계 계산이 bigint 타입 반환
441
+
442
+ **코드 예시 보충:**
443
+ ```typescript
444
+ import { from } from 'semantic-typescript';
445
+
446
+ // 숫자 통계
447
+ const numberData = from([10, 20, 30, 40, 50]);
448
+ const numericStats = numberData.toNumericStatistics();
449
+
450
+ console.log(numericStats.mean()); // 30
451
+ console.log(numericStats.summate()); // 150
452
+
453
+ // Big integer 통계
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
471
+ ```
472
+
473
+ ## 완전한 사용 예시
474
+
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
+ ```
513
+
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()` - Big integer 통계
524
+ - `sorted()` - 자연 정렬
525
+ - `sorted(comparator)` - 사용자 정의 정렬
526
+ 4. **터미널 연산**: Collectable 인스턴스에서 `toArray()`, `count()`, `summate()` 등 터미널 메서드 호출
527
+ 5. **데이터 검증**: `validate()`를 사용하여 데이터가 null/undefined가 아님을 보장, `invalidate()`를 사용하여 무효한 데이터 확인
528
+
529
+ 이 설계는 타입 안전성과 성능 최적화를 보장하면서 풍부한 스트림 처리 기능을 제공합니다.