[JavaScript] - sort(), reverse(), join()

Minji Kim·2022년 9월 14일
0
post-thumbnail

프로그래머스 Lv.1 정수 내림차순으로 배치하기 문제를 풀며 정리한 내용입니다.

문제

문제 설명

함수 solution은 정수 n을 매개변수로 입력받습니다. n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 예를 들어 n이 118372면 873211을 리턴하면 됩니다.

제한 조건

  • n은 1이상 8000000000 이하인 자연수입니다.

처음 구현한 코드

function solution(n) {
    let sortArr = (n+'').split('').map((str)=> parseInt(str)).sort((a,b)=> b-a)
    let num = parseInt(sortArr.reduce((acc,cur)=> acc+String(cur)))
    return num
}

내가 작성한 코드는 정수를 각 자릿수 별 쪼개고 sorting한 뒤에 문자열 방식으로 각 자릿수를 더하는 방식이다.
즉, 정수→문자→정수→문자→정수 이렇게 타입을 계속적으로 변환해줘야 한다.
아무리 봐도 비효율적이었지만, 아직 JS의 함수 메서드를 많이 모르기 때문에 아는 선에서 최선을 다해 그나마 풀었던 코드이다..

다른 사람 풀이를 본 후 구현한 코드

일단 sort 메서드에 대한 낮은 이해도 때문에 map 메서드를 불필요하게 사용했었다. 따라서 이를 제외하고 reverse 메서드와 join 메서드를 사용하고 +를 연산자를 사용하면서 보기 좋은 코드로 완성할 수 있었다.

function solution(n) {
    let sortArr = (n+'').split('').sort().reverse()
    let changeNum = sortArr.join('')
    return +changeNum
}

그래서 공부하게 된 함수 메서드는 array와 함께 사용하는 sort(), reverse(), join() 이다.

sort()

sort 메서드의 유의해야할 점을 먼저 살펴보자.

  1. 상식적으로 생각하는 오름차순 방식이 아닌 문자열의 유니코드 코드 포인트를 따른다.
  2. 원 배열이 복사되는 것이 아닌 원 배열이 정렬된다.

[예시 코드1]

const strArr = ['Minngki', 'World', 'Hello', 'Debugging']
console.log(strArr.sort()) // ['Debugging', 'Hello', 'Minngki', 'World']

const numArr = [1, 5, 2, 200, 10]
console.log(numArr.sort()) // [1, 10, 2, 200, 5] 

문자열 배열인 strArr은 우리의 예상대로 반환되었지만 숫자형 배열인 numArr은 우리가 예상했던 방향인 [1, 2, 5, 10, 200] 값으로 반환되지 않는다는 것이다.

그렇다면 이 방식대로 반환하기 위해서는 어떻게 코드를 작성해야 할까 ?

sort 함수의 구문을 살펴보자.

arr.sort([compareFunction])

compareFunction정렬 순서를 정의하는 함수로, 원하는 방식의 정렬을 정의해주면 된다. 이를 생략하면 문자열 유니코드 코드 포인트 값에 따라 정렬이 되는 것이다.

[예시 코드2]

const numArr = [1, 5, 2, 200, 10]
console.log(numArr.sort((a, b) => a-b)) // [1, 2, 5, 10, 200] - 오름차순
console.log(numArr.sort((a, b) => b-a)) // [200, 10, 5, 2, 1] - 내림차순

a-b ? b-a ? 이 차이는 무엇일까 ?

왜 이렇게 작동하는지 자세히 살펴보자면, compareFunction 의 원리는 다음과 같다.

compareFunction 원리

function compare(a, b) {
  if (a < b) {
    return 음수;
  } // compare 함수가 음수를 반환하면 a를 b보다 낮은 index로 정렬하므로, a가 먼저 와야 한다.
  if (a > b) {
    return 양수;
  } // compare 함수가 양수를 반환하면 b를 a보다 낮은 index로 정렬하므로, b가 먼저 와야 한다.
  if (a == b) {
  return 0;
  } // compare 함수가 0을 반환하면 a와 b는 순서를 바꾸지 않는다.
}

compare 함수의 인자에 따른 반환값이 음수, 양수, 0 냐에 따라 정렬 방식이 달라진다는 것이다.

숫자형 정렬하는 compareFunction

[예시 코드2]로 돌아와보자면,

const numArr = [1, 5, 2, 200, 10]
console.log(numArr.sort((a, b) => a-b))
// 1-5 = -4 음수이므로 1이 5보다 낮은 인덱스, 5-2 = 3 양수이므로 2가 5보다 낮은 인덱스 (반복)
console.log(numArr.sort((a, b) => b-a))
// 5-1 = 4 양수이므로 5가 1보다 낮은 인덱스, 1-2 = -1 음수이므로 2가 1보다 낮은 인덱스 (반복)

이 예시는 문자열이 아닌 숫자를 비교하기 위한 compare 함수이며, 원소에는 InfinityNaN이 포함되어 있지 않아야 한다.
해당 함수는 숫자 간의 단순계산을 하여 음수, 양수, 0 이 세 가지가 모두 반환이 가능하므로 정상 작동한다.


그러나! 문자열을 비교하는 compare함수를 작성할 시 주의할 점이 있다.

문자열 정렬하는 compareFunction

compareFunction의 반환값은 항상 음수, 0, 양수 의 값을 반환해야 한다.
양수/음수 만 반환한다거나 음수/0만 1-2가지의 값을 반환하면 원하는 방향의 정렬을 하지 못 할 것이다.
따라서, 문자열을 비교할 때 compareFunction을 작성할 땐 세 가지 경우의 if문을 사용해야 한다는 것을 유의하자!

[추가 - 문자열]
문자열을 비교할 때, 일반적으로 영문 대소문자 중 대문자가 앞에 온다. (오름차순이라면 대-소 순서)

sort()의 응용

  1. Object 정렬

Object의 프로퍼티를 이용해서 내부의 정렬을 정의할 수 있다.

[예시 코드3]

const market = {
  name: 'emart',
  fruits: [
  {
  	name: 'banana',
  	price: 2000,
  },
  {
  	name: 'apple',
  	price: 3000,
  },
  {
  	name: 'cherry',
  	price: 1000,
  }]}

market.fruits.sort((a,b)=> {
  return a.price-b.price })
console.log(market)

    // {
    // name: 'emart',
    // fruits: [
    // {
    //     name: 'cherry',
    //     price: 1000,
    // },
    // {
    //     name: 'banana',
    //     price: 2000,
    // },
    // {
    //     name: 'apple',
    //     price: 3000,
    // }] 

문자열인 market.fruits.name도 정렬이 가능하다.

// 오름차순 기준, 내림차순이면 각 연산자를 반대로 설정해주면 된다.
market.fruits.sort((a,b)=> {
	if (a.name < b.name) {
      return -1
    }
  	if (a.name > b.name) {
      return 1
    }
  	return 0
})
    // {
    // name: 'emart',
    // fruits: [
	// {
    //     name: 'apple',
    //     price: 3000,
    // },
    // {
    //     name: 'banana',
    //     price: 2000,
    // },
    // {
    //     name: 'cherry',
    //     price: 1000,
    // }
    // ] 
  1. 조건부 정렬

if문을 사용해서 정렬에 대한 조건을 직접 정의할 수 있다.

[예시 코드4]

const numArr = [0, 0, 0, 3, 4, 2];

numArr.sort((a,b)=>{
	if (a===0) { // 앞에 있는 원소가 0이라면 1(양수)을 반환하여 0이 아닌 다른 수를 낮은 인덱스로 취하고,
    	return 1;
    } else if (b===0) { // 뒤에 있는 원소가 0이라면 -1(음수)을 반환하여 0이 아닌 다른 수를 낮은 인덱스로 취한다.
    	return -1;
    } else { // 비교하는 원소가 모두 0이 아니라면 오름차순을 취해 반환한다.
    	return a-b;
    }
} // [2, 3, 4, 0, 0, 0]

그래서 예전에 공부할 때도 sort 함수를 마구잡이로 활용해선 안 되겠다 란 강렬한 인상이 남아서인지, 이번 연습문제를 풀 때는 완전 꼬아서 생각했다.
연습문제에서는 어차피 한 자릿수로 쪼개서 비교하는 것이기 때문에 두 자리에서의 문자열 유니코드를 굳이 고려하지 않고 간단하게 reverse 메서드를 사용했으면 됐었다.

reverse()

원 배열의 순서를 반전하여 변형된 원 배열을 반환한다. 원 배열의 인덱스를 내림차순으로 변형시키는 메서드라 생각하면 쉽다.

array.reverse()

[예시 코드5]

const arr = [1, 2, 3]

const reverseArr = arr.reverse()
console.log(reverseArr) // [3, 2, 1]

// 주의 !
console.log(arr) // [3, 2, 1] - 원 배열도 reverse된 형태로 변형된다.
console.log(arr[0]) // 3 - 인덱스도 변경된다.

join()

join 메서드는 배열의 모든 요소를 연결하여 하나의 문자열로 반환한다.

array.join([seperator])

seperator는 배열의 각 요소를 연결할 때 구분할 문자열이다. 생략하면 배열의 요소가 쉼표로 구분이 되고, 빈 문자열이면 아무 문자 없이 연결된다.

[예시 코드6]

const array = ['min','ng','ki'];
console.log(array.join()); // 'min,ng,ki'
console.log(array.join('')); // 'minngki'
console.log(array.join('-')); // 'min-ng-ki'

알고나면 너무나 쉬운 join 메서드..
이 꿀 같은 join 메서드를 항상 잊는다..바보처럼..

잊지말자.. join...

알게 된 점

  1. 끝에 더하는 타입에 따라 반환되는 타입이 변경된다.
    숫자형 + 문자열 = 문자열 반환, 문자열 + 숫자형 = 숫자형 반환
    • 추가로 return +문자열변수 에 대한 설명을 하자면,
      return할 때 +를 붙임으로써 문자열 변수가 숫자형으로 변환되어 반환된다.
  2. sort, reverse, join 메서드의 원리

참고

https://developer.mozilla.org/ko/
https://brunch.co.kr/@swimjiy/12

profile
애기코더 응애

0개의 댓글