JavaScript/함수형 프로그래밍과 JavaScript ES6+

2차원 배열 다루기

느리지만 꾸준하게 2021. 8. 24. 21:44

아래와 같이 생긴 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