안녕하세요. 이번에는 K번째 수라는 프로그래머스 문제를 풀어보겠습니다.
문제는 다 알고 왔다는 전제하에 설명하겠습니다.
이번엔 답부터 적겠습니다.
function solution(array, commands) {
return commands.map((command) => {
const [i, j, k] = command;
return [...array].splice(i - 1, j - i + 1).sort((a, b) => a - b)[k - 1]
})
}
solution([1, 5, 2, 6, 3, 7, 4], [[2, 5, 3], [4, 4, 1], [1, 7, 3]])
> [5, 6, 3]
forEach가 아닌 map을 사용한 이유는?
forEach를 쓰면 콜백함수내에서 값을 반환해도 그 값을 받을 수 없기 때문에 map 함수를 써서 콜백함수 내에서 뱉은 값을 이용해 새로운 배열로 만들고자 했습니다.
이것은 구조 분해 할당이라는 것으로 우항에 있는 리터럴 또는 값을 좌항으로 분해하는 표현식입니다. 위의 식은 배열 구조 분해고 객체 구조 분해라는 것도 있습니다.
// 객체는 배열처럼 대입할 수 없더라고요. -> ()로 감싸기
// { a, b } = { a: 10, b: 20 } -> 실행 오류
여기서 좌항의 구조 분해를 받는 변수의 이름이 같아야 해요!
만약 같지 않다면 undefined로 할당 받아요!
({ c, d } = { a: 10, b: 20 })
console.log(c, d); // undefined undefined
... 연산자: 스프레드 연산자
저는 이걸 배웠을 때 이게 뭐야~ 하고 그냥 넘어갔었습니다.
그런데 계속 공부를 하고 프로그래밍 문제를 풀다보니까 ... 연산자가 필요할 때가 엄청 많더라고요.
이 연산자를 쓰면 객체와 배열을 깊은 복사가 아닌 얕은 복사를 할 수 있어요.
원시 타입: 얕은 복사, 참조 타입: 깊은 복사 라고 생각하셔도 전 아직까지 무방했습니다.
깊은 복사의 문제점이라면 값이 바뀌면 그걸 참조하고 있는 모든 변수들의 값도 같이 변한다는 것이죠.
const arr = [1, 2, 3];
const copy = arr;
arr[0] = 0;
console.log(arr, copy) // [0, 2, 3] [0, 2, 3]
위와 같이 참조하고 있는 모든 변수들의 값이 바뀐것을 확인할 수 있습니다.
이는 참조 타입이 객체의 값을 저장하고 있는 번지를 참조하기 때문이라고 간략하게 설명하겠습니다.
이럴 때 spread 연산자를 이용하면 참조하는 값을 복사해서 새로운 객체로 만들어줍니다.
const a = [1];
const b = [...a];
const c = Array.from(a); // 이 함수 또한 ES6에서 새롭게 추가된 함수에요.
a === b // false
b === c // false
a === c // false
다른 예제들을 보니까 splice가 아닌 slice를 많이 사용하셨더라고요.
그런데 저는 예전부터 splice를 사용해서 그냥 splice를 사용했습니다.
그리고 둘 모두 인자만 잘 넘겨준다면 같은 결과를 낼 수 있습니다.
전 이 sort() 때문에 한 10분을 빼먹은 거 같습니다.
처음 제가 이 함수를 쓸 때는 인자로 아무것도 주지 않았습니다.
왜냐하면 어차피 sort()에 아무것도 주지 않으면 알아서 오름차순으로 정렬을 해주기 때문입니다.
그런데 프로그래머스 테스트 케이스를 만든 사람이 이 허점을 노리셨는지 인자를 제대로 주지 않으면 오류를 내는 케이스를 추가하셨더라고요...
여러분은 저 처럼 그냥 sort()해서 풀지 마세요! 시간이 사라집니다.
프로그래머의 기본 소양은 꼼꼼함이다.
내가 대충 생각했던 sort() 함수 하나가 나의 결과를 바꿔놓을 수 있다는 것을 간과해서는 안된다는 것을 다시 한 번 깨달았습니다.