아래와 같이 생긴 2차원 배열이 있다. flatten이나 기존에 작성했었던 지연적으로 동작하는 함수들을 조합하여서 2차원 배열을 다루는 코드를 작성해보자.
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
array로 부터 시작을 하고 log를 통해 출력을 하면 받은 값 그대로 나타난다.
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
log);
</script>
만약 flatten을 한다면 펼쳐주게 되고 이후에 filter라는 함수를 통해 홀수만 남기는 식으로 작성할 수 있다.
go(arr,
flatten,
filter(a => a % 2),
log);
// (5) [1, 3, 5, 7, 9]
L.flatten이 되어도 동일한 결과를 만들 것이고
go(arr,
L.flatten,
filter(a => a % 2),
log);
// (5) [1, 3, 5, 7, 9]
L.filter을 하면 지연된 상태의 값이 된다.
go(arr,
L.flatten,
L.filter(a => a % 2),
log);
// Generator {<suspended>}
takeAll을 이용해 모두 가져온다거나 앞에서 3개만 가져오든지 하는 것을 했을 때 앞에 L.flatten과 L.filter은 지연되면서 flatten이 1을 펼쳐서 filter에 가보고 filter에 가서 홀수인지를 보고 그리고 take로 내려가서 take에서 하나를 꺼내서 담아두고
다음으로 갔을 때 2를 펼쳐보고 2를 펼쳐서 filter에 가서 확인해보고 짝수이니까 take에 가지않고 다시 flatten에서 다음 값을 꺼낸다.
즉 flatten에서 하나 집은다음 filter해보고 여기서 조건에 부합되면 take를 통해 담을지 말지 보고 하는 것이다.
go(arr,
L.flatten,
L.filter(a => a % 2),
take(3),
log);
// (3) [1, 3, 5]
L.flatten에서 확인해보면 1~5 까지만 순회하는 것을 볼 수 있다.
뒤에 6 이상부터는 take(3)을 했기 때문에 순회를 하지 않는 것이다.
const isIterable = a => a && a[Symbol.iterator];
L.flatten = function* (iter) {
for (const a of iter) {
console.log(a);
if (isIterable(a)) for (const b of a) yield b;
else yield a;
}
};
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
L.flatten,
L.filter(a => a % 2),
take(3));
</script>
그리고 L.flatten을 지정한 함수에서 yield한 모든 값들을 본다면 일단 아래와 같이 나타내어 주고
take(2)를 해주면 3까지만 순회하는 것을 볼 수 있다.
L.flatten = function* (iter) {
for (const a of iter) {
if (isIterable(a)) for (const b of a) { console.log(b); yield b }
else yield a;
}
};
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
L.flatten,
L.filter(a => a % 2),
take(2));
</script>
// 1
// 2
// 3
만약에 L.flatten이 아니고 flatten이면 모두 순회하고 filter를 통해서 넘어가는 것이다.
## 2차원 배열 다루기
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
flatten,
filter(a => a % 2),
take(2));
</script>
//1
//2
//3
//4
//5
//6
//7
//8
//9
//10
즉 L.flatten과 L.filter를 하면 지연적으로 동작하기 때문에 필요한 값까지만 순회를 하고 원하는 만큼 take 될 때까지 순회를 하는 것이다.
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
L.flatten,
L.filter(a => a % 2),
take(4));
</script>
//1
//1prac.html:13 2
//1prac.html:13 3
//1prac.html:13 4
//1prac.html:13 5
//1prac.html:13 6
//1prac.html:13 7
L.map을 해서 제곱 값을 나타낼 수도 있고,
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
L.flatten,
L.filter(a => a % 2),
L.map(a => a * a),
take(4),
log);
</script>
// (4) [1, 9, 25, 49]
모두 합산을 하겠다 해서 reduce를 통해 나타낼 수도 있다.
<script>
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
L.flatten,
L.filter(a => a % 2),
L.map(a => a * a),
take(4),
reduce(add),
log);
</script>
//84
<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>
https://www.inflearn.com/course/functional-es6/dashboard
함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의
ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,
www.inflearn.com
'JavaScript > 함수형 프로그래밍과 JavaScript ES6+' 카테고리의 다른 글
이터러블 중심 프로그래밍 실무적인 코드 (0) | 2021.08.25 |
---|---|
L.flatMap, flatMap (0) | 2021.08.24 |
L.flatten, flatten (0) | 2021.08.24 |
L.map L.filter로 map과 filter 만들기 (0) | 2021.08.24 |
take, find (0) | 2021.08.24 |