[CodeKata] topK 함수 구현하기
문제
nums
는 숫자로 이루어진 배열이다. 가장 자주 등장한 숫자를 k
갯수만큼 return해 주세요.
ex.
nums = [1, 1, 1, 2, 2, 3];
k = 2;
// return : [1, 2]
nums = [1];
k = 1;
// return [1]
풀이
function topK(nums, k) {
let obj = {};
nums.map(num => {
if(obj[num]){
obj[num] = obj[num]+1
} else {
obj[num] = 1
}
})
let objSort = Object.keys(obj).sort((a,b) => {return obj[b]-obj[a]});
return objSort.slice(0, k).map(e => Number(e));
}
객체 만들기
obj
객체에 obj[num]
(nums 배열의 각 숫자값이 객체의 key값이 된다)이 있으면 1씩 증가하며, 만약 없다면 1을 할당한다.
만약 nums
에 [3, 3, 3, 4, 4, 4, 4, 2, 2, 2, 2, 2, 1]이 담겨있다면 obj
의 값은 {'1': 1, '2': 5, '3': 3, '4': 4}
이 된다.
arr.sort()
위 obj
의 값을 key에 담겨있는 값의 크기대로 내림차순으로 정렬하고자 한다. 이를 위해서 sort
를 사용했다. sort
는 arr.sort([compareFunction])
과 같은 구문으로 되어 있으며 [compareFunction]
을 생략해서 사용하면 요소를 문자열로 변환하고 유니코드 코드 포인트 순서로 문자열을 비교하여 정렬하게 된다.
[compareFunction]
이 잘 이해가지 않는다면 다음 예시를 확인해야 한다. 문자열에서 apple은 banana 앞에 온다. 숫자에서 10은 3보다 뒤에 오지만, 문자열로 변환되면 10은 유니코드에서 3보다 앞에온다.
console.log( [10, 3, 24, 42, 41, 1].sort() );
// 결과 : [ 1, 10, 24, 3, 41, 42 ]
MDN에는 다음과 같이 정의되어 있다.
- compareFunction(a, b)이 0보다 작은 경우 a를 b보다 낮은 색인으로 정렬합니다. 즉, a가 먼저옵니다.
- compareFunction(a, b)이 0을 반환하면 a와 b를 서로에 대해 변경하지 않고 모든 다른 요소에 대해 정렬합니다.
- compareFunction(a, b)이 0보다 큰 경우, b를 a보다 낮은 인덱스로 소트합니다.
첫 번째 정의를 해석하면 a-b < 0 이면 a < b 라는 의미이며, 이 경우에 낮은 색인인 a가 먼저온다는 것은 오름차순으로 정렬하는 것이다.
MDN에도 "문자열 대신 숫자를 비교하기 위해 compare 함수는 a에서 b를 뺄 수 있습니다. 다음 함수는 배열을 오름차순으로 정렬합니다"라고 쓰여있다. 내림차순으로 정렬하기 위해서 (a,b) => {return obj[b]-obj[a]}
와 같이 입력했다.
k만큼 가져오기
slice
를 사용하여 0번째 인덱스부터 k번째 인덱스(포함X)까지 가져온 배열을 map
함수로 각 요소를 문자열에서 숫자로 바꾸어 숫자로 이루어진 배열을 반환하도록 하였다.