본문으로 바로가기

오늘도 문제 은행에서 시간이 많이 걸릴 줄 몰랐습니다....

오늘의 문제는 주어진 배열 내 요소들의 등장 횟수를 객체로 반환하는 문제였습니다.

1) getFrequency(arr)는 주어진 배열 내 요소들의 등장 횟수를 객체로 반환합니다. 
     예: getFrequency(["apple", "banana", "apple"]) -> { apple: 2, banana: 1 } 
2) reduce, forEach 등을 이용할 수 있습니다. 
3) 문자열, 숫자 등 어떤 타입이든 동작하도록 처리하세요.

 

3번이 내 문제가 될 줄은 생각도 안하고 있었는데 글쎄 바로 문제가 됐습니다.

 

기존 코드

function getFrequency(arr) {
    let newArr = {};
    arr.forEach((a) => {
        if(!newArr[a]){
            newArr[a] = 1
        }else{
            newArr[a] = newArr[a] + 1;
        }
    })
    return newArr;
}

 

객체로 반환할 것이기 때문에 새로운 객체를 만들어 준 후
주어진 배열을 순회하며 새로운 객체 내에 해당하는 키 값이 없을 경우 추가해주고

해당하는 키 값이 있을 경우 value 값을 +1 해줍니다.

 

 

arr가 [true, 'true', 1, '1', 1]로 주어졌을 경우 {true: 1, 'true': 1, 1: 2, '1': 1} 이렇게 결과값이 나올거라 예상했지만
{"1": 3, "true": 2}로 출력되었습니다.

 

 

JavaScript의 타입과 자료구조 - JavaScript | MDN

모든 프로그래밍 언어에는 내장된 자료구조가 존재하지만, 보통 그 내용은 언어마다 다릅니다. 이 글에서는 JavaScript에서 사용할 수 있는 내장 자료구조와 그 속성에 대해 알아보겠습니다. 그러

developer.mozilla.org

객체의 속성 키는 strings타입 또는 symbols타입이 될 수 있습니다.

 

이를 해결할 수 있는 방법이 뭐가 있냐.... 하면 바로 Map 객체가 있습니다.

 

Map - JavaScript | MDN

Map 객체는 키-값 쌍과 키의 원래 삽입 순서를 기억합니다. 모든 값(객체 및 원시 값 모두)은 키 또는 값으로 사용될 수 있습니다.

developer.mozilla.org

  Map Object
키 유형 Map의 키는 모든 값(함수, 객체 또는 원시값 포함)이 될 수 있습니다. Object의 키는 String 또는 Symbol이여야 합니다.

 

 

해결 코드

function getFrequency(arr) {
    let newArr = new Map();
    arr.forEach((a) => {
        if(!newArr.has(a)){
            newArr.set(a, 1);
        }else{
            newArr.set(a, newArr.get(a) + 1);
        }
    })
    return Object.fromEntries(newArr);
}

 

 

Map 객체를 생성한 후 arr.forEach로 배열을 순회하며 해당 키가 있는지 확인합니다.

키가 없으면 set 메서드로 초기 값을 1로 설정합니다.

키가 있으면 get 메서드로 기존 값을 가져와 1을 더해 업데이트합니다.

 

 

Object.fromEntries를 사용하여 Map 객체를 일반 객체로 변환합니다.(Map객체와 일반 객체는 다르기 때문에 문제 조건에 맞춰 일반 객체로 변환)

 

일단 통과는 했는데 console을 찍어보니

 

이 놈이 이렇게 나오는데.....?

 

debugger를 통해 코드가 제 예상대로 동작하는지 한번 확인해봅시다.

 

newArr가 {true: 1, 'true': 1, 1: 2, '1': 1} 이렇게 제 예상대로 출력되는 것을 볼 수 있습니다.

그렇다면 왜 도대체 왜 true와 1은 어디로 사라진건가....

 

Object.fromEntries()를 사용하면, 객체의 키는 항상 문자열로 변환되기 때문에, true, 1 등의 원시 타입 값은 문자열 'true', '1'로 변환됩니다.

이러한 이유로 뒤에 있는 'true'와 '1'이 앞쪽 값으로 오버라이딩 되면서 저런 예상치 못한 출력값이 나오게 된 것입니다...!