flatten을 lazy evaluation으로 만들기 위해 아래와 같은 함수를 작성했습니다.
depth를 2 이상 가진 배열을 돌리면, 완전히 flatten되지 않습니다.
우선 위 함수 내부에 for...of 문이 중첩되어 들어가는 것이 가독성이 좋지 않게 보이므로 yield *를 활용하여 가볍게 만들겠습니다.
// iterable 안의 값도 iterable이면 펼쳐내는 작업. 단, depth가 1인 경우만 됨
const faltten = function* (iter) {
for (const val of iter) {
if (isIterable(val)) {
for (const inner of val) {
yield inner;
}
} else {
yield val;
}
}
};
console.log([...faltten([1, 2, [3, 4]])]); // [1, 2, 3, 4]
yield* 란, iterable의 값들을 하나씩 펼쳐나가는 과정입니다.
// iterable인 a의 iterator의 value값을 for..of 문으로 뿌립니다.
for (const b of a) {
yield b;
}
// 아래로 변경합니다.
yield* a;
결론적으론 아래와 같이 줄일 수 있습니다.
const flatten = function* (iter) {
for (const val of iter) {
if (isIterable(val)) yield* val;
else yield val;
}
};
아주 간단히 generator를 만들어보자면 아래와 같이 for...of 없이도 편리하게 iterator를 정의할 수 있습니다.
const testGen = function* (iter) {
yield* iter;
};
const iter = testGen([1, 2, 3]);
console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.next()); // { value: 3, done: false }
console.log(iter.next()); // { value: undefined, done: true }
이제 depth가 2 이상인 배열도 flatten할 수 있도록 만들겠습니다. 이를 위해서 재귀적으로 실행하게 만들어야 합니다.
generator를 재귀적으로 실행할 수 있도록 함수형태로 만든 후에 yield* 에 값이 안인 함수를 배당하겠습니다.
L.deepFlatten = function* f(iter) {
for (const val of iter) {
if (isIterable(val)) yield* f(val);
else yield val;
}
};
console.log([...flatten([1, 2, [3, 4, [5, 6]]])]); // [1, 2, 3, 4, 5, 6]
'Programming Language > 🟨 Javascript (Core)' 카테고리의 다른 글
__proto__ vs prototype (0) | 2021.06.10 |
---|---|
javascript 모듈 시스템 : CJS, AMD, UMD, ESM (0) | 2021.05.30 |
iteration : iterable(순회할 수 있는 객체)와 iterator(순환체) (0) | 2021.05.23 |
Reflect, Proxy (1) : Reflective 프로그래밍을 위한 표준 내장 객체들 (0) | 2021.04.16 |
TS로 살펴보는 Promise + Promise.all 병렬처리 (0) | 2020.08.25 |