L.flatten이라는 함수를 만들어본다.
예를 들어 아래와 같이 값이 들어있다고 했을 때
값을 다 펼쳐서 하나의 배열로 만드는 것을 하기위해 사용하는 함수이다.
<script>
log([...[1, 2], 3, 4, ...[5, 6], [7, 8, 9]]);
</script>
그러면서 동작을 지연적으로 하는 함수인데 구현을 해보자.
L.flatten을 만들면 이터러블 프로토콜을 이용한 지연적으로 동작함수를 만들기 위해서 제너레이터로 함수를 선언한다.
L.flatten = function *() {
};
L.flatten은 iter값을 받아서 for of를 통해서 순회를 하고 순회를 하면서 a라는 값이 만약에 이터러블이면 계속 펼쳐서 yield하는 식으로 동작을 시켜준다. isIterable이면 어떤 일을 하고 이터러블이 아니면 값을 그대로 yield를 하는 함수를 만든다.
L.flatten = function *() {
for (const a of iter) {
if (isIterable(a)) {}
else yield a;
}
};
isIterable같은 경우에는 아래와 같이 a라는 값을 받아서 a가 Symbol.iterator를 가지고 있는지 보는 정도로 구현한다.
const isIterable = a => a[Symbol.iterator];
L.flatten = function* () {
for (const a of iter) {
if (isIterable(a)) { }
else yield a;
}
};
그 전에 nullable한 값이 올 수 있기 때문에 &&연산자를 이용한다.
const isIterable = a => a && a[Symbol.iterator];
만약 iterable인 경우에는 한번 더 순회를 하는 식으로 구현해주면 a 안에 있는 모든 값들을 yield 하는 식으로 작성해준다.
L.flatten = function* () {
for (const a of iter) {
if (isIterable(a)) for (const b of a) yield b;
else yield a;
}
};
아래와 같은 array가 있다고 했을 때 L.flatten을 해주면 이터레이터가 리턴되는데 이터레이터를 next를 해서 log를 찍어보면 하나가 꺼내지게 된다.
[[1, 2], 3, 4, [5, 6], [7, 8, 9]]
const it = L.flatten([[1, 2], 3, 4, [5, 6], [7, 8, 9]]);
log(it.next());
//(7) [1, 2, 3, 4, 5, 6, Array(3)]
// 1prac.html:20 {value: 1, done: false}
계속해서 next를 하게 되면 flat하게 펼쳐진 결과를 볼 수 있다.
const it = L.flatten([[1, 2], 3, 4, [5, 6], [7, 8, 9]]);
log(it.next());
log(it.next());
log(it.next());
//(7) [1, 2, 3, 4, 5, 6, Array(3)]
//1prac.html:20 {value: 1, done: false}
//1prac.html:21 {value: 2, done: false}
//1prac.html:22 {value: 3, done: false}
즉 이러한 이터레이터를 이용해서 한번에 펼쳐줄 수 있다.
결론
L.flatten은 동적으로 array들을 한 번에 펼쳐서 한 depth를 가진 array로 일차원 배열로 변형해주는 이터레이터를 리턴하는 함수가 된다.
const it = L.flatten([[1, 2], 3, 4, [5, 6], [7, 8, 9]]);
log([...it])
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
바로 모든 평가가 이뤄지는 것은 아니고 원하는 만큼 평가를 하면서 값을 얻을 수 있는 것이다.
const it = L.flatten([[1, 2], 3, 4, [5, 6], [7, 8, 9]]);
// log([...it])
log(it.next());
log(it.next());
log(it.next());
log(it.next());
//(7) [1, 2, 3, 4, 5, 6, Array(3)]
//1prac.html:21 {value: 1, done: false}
//1prac.html:22 {value: 2, done: false}
//1prac.html:23 {value: 3, done: false}
//1prac.html:24 {value: 4, done: false}
L.flatten이 있으면 즉시 모두 펼친 값을 만드는 즉시 평가하는 flatten도 쉽게 만들 수 있다.
즉시 평가하는 flatten이라는 함수는 L.flatten을 하고 해당하는 모든 값을 takeAll을 통해서 모두 평가를 해서 꺼내놓겠다라고 하면 모두 펼친 값을 만들 수 있다.
const flatten = pipe(L.flatten, takeAll);
log(flatten([[1, 2], 3, 4, [5, 6], [7, 8, 9]]));
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
그리고 아래 L.flattne 같은 경우는 지연적으로 동작하기 때문에 아래와 같이 사용할 수도 있다.
즉 펼쳐진 것 중에서 3개의 값만 take를 통해 보여주는 것이다.
log(take(3, L.flatten([[1, 2], 3, 4, [5, 6], [7, 8, 9]])));
// (3) [1, 2, 3]
<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>
https://www.inflearn.com/course/functional-es6/dashboard
함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의
ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,
www.inflearn.com
'JavaScript > 함수형 프로그래밍과 JavaScript ES6+' 카테고리의 다른 글
2차원 배열 다루기 (0) | 2021.08.24 |
---|---|
L.flatMap, flatMap (0) | 2021.08.24 |
L.map L.filter로 map과 filter 만들기 (0) | 2021.08.24 |
take, find (0) | 2021.08.24 |
Array.prototype.join 보다 다형성이 높은 join 함수 (0) | 2021.08.24 |