ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 고차함수 - Sort(), reverse()
    프론트엔드/JavaScript 2020. 10. 3. 02:56

    sort(), reverse()의 문제점

    자바스크립트에서는 배열을 정렬하는 Sort()라는 메서드가 있다.

     

    <body>
        <script>
    
            let num = [100,50,30,20,10,5,3,7,77,10];
    
            num.sort();  // 올림차순 정렬
    
            console.log(num);
            // [100, 50, 30, 20, 10, 5, 3, 7, 77, 10]
            // 요소를 유니코드로 바꾼 후 비교후 올림차순 정렬.
    
            num.reverse();  // 내림차순 정렬
    
            console.log(num);
            // [77, 7, 50, 5, 30, 3, 20, 100, 10, 10]
            // 요소를 유니코드로 바꾼 후 비교후 내림차순 정렬. 
    
        </script>
    </body>

     

    이 메서드를 이용하면 위 코드처럼 유니코드에 의거해서 배열의 요소들을 오름차순에 따라 정렬한다.

     

    내림 차순으로 정렬하고 싶을 땐 reverse() 메서드를 사용하면된다.

     

    그런데 뭔가 좀 이상하다.

     

    숫자 배열의 경우 해당 숫자를 숫자로서 비교하는 것이 아니다.

     

    유니코드로 변환하여 문자열처럼 비교하므로 결과가 이상하게 나온다.

     

    배열이 문자열일때는 괜찮은데, 숫자 배열의 경우 단순 sort(), reverse()로는 정렬에 오류가 난다.

    고차함수를 활용한 sort 활용법

    이럴 때는 고차함수를 활용하여 sort 메서드의 정렬 기준을 다시 설정해주면 된다.

     

    우선 코드를 보자.

     

    <body>
        <script>
    
            let num = [100,50,30,20,10,5,3,7,77,10];
    
            num.sort(function(x,y){return x-y});
            // sort 메서드에 함수를 인수로 준다.
            // 이 함수는 요소들을 직접 숫자로 비교해서 정렬
    
            console.log(num);
            // [3, 5, 7, 10, 10, 20, 30, 50, 77, 100]
            // 올림 차순으로 숫자가 제대로 정렬됨
    
        </script>
    </body>

     

    위 코드를 보면 sort() 메서드의 인수로 함수를 전달해서 배열의 요소를 빼가며 비교한다.

     

    그리고 그 결과 유니코드로 비교한 값이 아닌 제대로 된 숫자 정렬이 진행됐다.

     

    저 코드를 풀어쓰면 이렇다.

     

    <body>
        <script>
    
            let num = [100,50,30,20,10,5,3,7,77,10];
    
            num.sort(function(x,y){
                if (x>y) {return 1}  // x가 크면 1 반환
                else if (x<y) {return -1} // y가 크면 -1 반환
                else if (x=y) {return 0}  // 같으면 0
            });
    
            console.log(num);
            // [3, 5, 7, 10, 10, 20, 30, 50, 77, 100]
    
        </script>
    </body>

     

    x와 y를 비교해서 x가 크면 1 즉 true, y가 크면 -1 즉 false, 같으면 0을 반환한다.

     

    이렇게 x,y에 들어가는 배열들의 값을 비교하면서 순서를 정렬하는 것이다.

     

    그렇다면 이제 역정렬을 하려면 어떻게하면 될까?

     

    <body>
        <script>
    
            let num = [100,50,30,20,10,5,3,7,77,10];
    
            num.sort(function(x,y){return y-x});
            // sort 메서드에 함수를 인수로 준다.
            // 이 함수는 요소들을 직접 숫자로 비교해서 정렬
            // 이때 내림 차순이므로 x-y가 아닌
            // y-x를 쓴다.
    
            console.log(num);
            // [100, 77, 50, 30, 20, 10, 10, 7, 5, 3]
            // 내림 차순으로 숫자가 제대로 정렬됨
    
        </script>
    </body>

     

    답은 간단하다 x에서 y를 빼주던 것을 반대로 y에서 x를 빼주면 된다.

     

    두 배열을 비교해서 음수가 나와야 true라고 설정하면 배열을 내림차순으로 진행된다.

    sort를 이용해 객체 정렬하기

    고차함수를 활용해 sort의 내용들도 정렬해줄 수 있다.

     

    예를 들어 각 정보를 가진 객체를 요소로 가진 배열이 있다고 생각해보자.

     

    코드는 다음과 같다.

     

    <body>
        <script>
    
            let hero = [
                {name: "헐크", age: "34"},
                {name: "배트맨", age: "37"},
                {name: "스파이더맨", age: "27"},
                {name: "슈퍼맨", age: "39"},
                {name: "아이언맨", age: "31"},
            ]
    
            hero.sort();  // 정렬 진행
    
            console.log(hero);  // 변화없음
    
        </script>
    </body>

     

    위 코드의 결과는 위에 적은 대로 아무런 변화가 없다.

     

    왜냐면 sort가 어떤 것을 기준으로 객체를 정렬할 줄 모르기 때문이다.

     

    sort는 name, age 둘 중 어떤 것으로 정렬할지 지정하지 않으면 모른다.

     

    이럴 때는 고차함수를 이용하면 된다.

     

    방법은 같다. 위의 sort를 활용한 것처럼 sort 안에 함수를 인수로 주면된다.

     

    그리고 그 함수는 객체의 정렬 기준을 결과값으로 반환해준다.

     

    <body>
        <script>
    
            let hero = [
                {name: "헐크", age: "34"},
                {name: "배트맨", age: "37"},
                {name: "스파이더맨", age: "27"},
                {name: "슈퍼맨", age: "39"},
                {name: "아이언맨", age: "31"},
            ]
    
            let name = function(a, b){
                if (a.name > b.name){return 1}
                else if (a.name < b.name){return -1}
                else return 0;
            } // 배열에 든 각 객체의 이름을 비교
    
            hero.sort(name);
            // 위에 설정한 name 함수를 sort의 인자로 제공
            // sort는 name에서 설정한 기준에 따라 요소들을 비교하여 정렬
    
            console.log(hero);
            // 배트맨, 슈퍼맨, 스파이더맨, 아이언맨, 헐크
            // 이름순으로 정렬
    
        </script>
    </body>

     

    위의 sort 정렬보다 조금 더 깔끔하게 했다.

     

    정렬 기준을 별도의 함수로 선언한 뒤에 sort 메서드 안에 메서드로 제공했다.

     

    sort 메서드 안에 직접 함수를 써줄 수도 있지만 내용이 길어지면 별도로 써서 넣어줘도 된다.

     

    그렇다면 이제 나이순으로 정렬하려면 어떻게 해야할까? 답은 아래 코드와 같다.

     

    <body>
        <script>
    
            let hero = [
                {name: "헐크", age: "34"},
                {name: "배트맨", age: "37"},
                {name: "스파이더맨", age: "27"},
                {name: "슈퍼맨", age: "39"},
                {name: "아이언맨", age: "31"},
            ]
    
            let age = function(a, b){
                if (a.age > b.age){return 1}
                else if (a.age < b.age){return -1}
                else return 0;
            } // 배열에 든 각 객체의 이름을 비교
    
            hero.sort(age);
            // 위에 설정한 age 함수를 sort의 인자로 제공
            // sort는 age에서 설정한 기준에 따라 요소들을 비교하여 정렬
    
            console.log(hero);
            // 스파이더맨, 아이언맨, 헐크, 배트맨, 슈퍼맨
            // 나이순으로 정렬
            
        </script>
    </body>

     

    위의 예시와 같이 고차함수를 이용하면 sort 함수의 정렬 기준을 정할 수 있다.

     

    그렇게 원하는대로 배열의 요소들을 정렬할 수 있다.

Designed by Tistory.