230222_TIL

reggias·2023년 2월 23일
0

I learned

목록 보기
46/62

최빈값을 구하는 알고리즘을 만드는 문제인데 아직 내 수준으로는 2가지 이상의 최빈값을 찾아내는 코드를 만들기가 어려운 것 같음.

Q. 최빈값은 주어진 값 중에서 가장 자주 나오는 값을 의미합니다. 정수 배열 array가 매개변수로 주어질 때, 최빈값을 return 하도록 solution 함수를 완성해보세요. 최빈값이 여러 개면 -1을 return 합니다.

What was the problem

예를 들면 [1,2,3,3,4] 에서 최빈값은 3이고 [1,1,2,2]에서 최빈값은 1과 2인데 최빈값이 두 가지 이상이면 -1 을 리턴하라는 것이다. 근데 최빈값이 두 가지 이상일 때에는 어떻게 코드를 짜야할지 구상은 나오지만 만들 수가 없다.

의사코드를 먼저 적어보자면
1. 숫자를 먼저 오름차순 정렬시키고
2. 앞숫자가 뒷숫자와 동일한지 확인하고
3. 동일하면 카운트를 1 세고 그렇지 않으면 카운트를 세지 않음
4. 뒷숫자가 존재하지않으면 반복문을 멈춤
5. 최빈값이 두 개 이상일 경우?
6. count가 1보다 큰 상태에서 인덱스 i와 i+1 가 동일하다면 count를 1 추가
7. 동일하지않다면 count를 1 추가하지않음.
8. 그 상태에서 다음 인덱스 i와 i+1 가 동일하다면 새로운 변수 count 를 생성
9. 생성한 변수 count2 = 2 반복문 종료시 새로 생성된 count(숫자)가 있는지 확인하고 없으면 그대로 count 출력, 있으면 count2와 비교하고 같으면 -1 출력, 틀리면 둘중 더 큰 것을 출력

Things i tried

All code

function solution(array) {
    let count = 1;
    const SortArray = array.sort((a, b) => a - b) // 오름차순 정렬

    for(let i=0;i<SortArray.length;i++) {
        if (SortArray[i] === SortArray[i+1]) {
            count += 1;
        } else {
            count = count;
        }
    }
    return count;
}
  1. 1~4번까지는 내 생각대로 구현함.
console.log(solution([1, 1, 2, 2])) // 3
console.log(solution([1, 2, 3, 3, 3, 4])) // 3
console.log(solution([1, 3, 2, 3, 3, 4, 3])) // 4
  1. 동적으로 변수를 만들어야겠다고 생각해서 구글링하다가 eval() 함수가 도움된다고 하는걸 봤지만 너무 어려워서 다른 방법을 찾기로함
  1. 구글링을 계속하다가 reduce와 lodash로 최빈값을 구하는 방법이 있다고 하길래 찾아봤음.
    reduce와 lodash로 최빈값을 계산해보자
    글쓴이가 현직 웹개발자라고 소개하고 있으니 정보에 대한 신뢰성이 생겨 이것을 공부해보기로 했음.

정석적인 풀이 절차

1) 정리된 결과를 보여줄 새로운 newObject를 선언
2) 배열을 순회하면서 해당하는 value들을 키값, count를 value로 하는 object를 만듦
3) newObject의 첫번째 키값과 첫번째 value값을 임시로 최빈값으로 지정해준다.(modeValue, modeKey)
4) newObject의 키값들을 순회하면서 더 큰 value가 있다면 modeValue와 modeKey를 바꿈
5) 결과값을 리턴

const arr = [100, 200, 300, 200, 200, 500, 500, 600];

const getMode = (arr) => {
  /**
   * 1. 배열들을 순회하면서 해당하는 value들을 키값, count를 value로 하는 Object를 만든다.
   * 2. 만들어진 Object에 있는 value들을 확인하며 최대값을 확인한다.
   */
  const newObject = {};
  arr.forEach((item) => {
    if (newObject[item]) {
      newObject[item] += 1;
    } else {
      newObject[item] = 1;
    }
  });

  /*
  만들어진 새로운 newObject에서 첫번째 값을 최빈값으로 설정해두고
  Object.keys로 순회하면서 더 큰 value를 가진 값이 있으면 mode를 바꾸어 준다.
  */
  let modeValue = newObject[Object.keys(newObject)[0]];
  let modeKey = Object.keys(newObject)[0];

  for (const item in newObject) {
    if (newObject[item] > mode) {
      mode = newObject[item];
      modeKey = Object.keys(newObject)[mode];
    }
  }
  return modeKey;
};

const result = getMode(arr);
console.log(`Mode is ${result}`);

근데 코드에 치명적인 결함이 있다는 것을 알게 되고 멘붕이 왔음. 변수를 선언하시고 그 변수를 할당하는데 이름이 다르다던가 결과값이 올바르게 나오지 않는 문제를 발견함

how did you solve it?

튜터님에게 도움을 요청했더니 코드가 복잡하다 하시며 다른 코드를 주시길래 그걸로 공부하기로 했음.

function maxNumber(arr) {
    const countObj = {};
  
    arr.forEach((value) => {
      countObj[value] = countObj[value] ? ++countObj[value] : 1; // countObj에서 키값을 가져와서 undefined 라면 1, 숫자가 있다면 1을 더하고 재할당하기
      
      console.log(`countObj 에 ${value} 가 들어갔더니 ${value}의 갯수는 ${countObj[value]} 가 되었음. countObj 는 ${JSON.stringify(countObj)}\n`)
    });
  
    const max = Math.max(...Object.values(countObj)); // 밸류값중에서 제일 높은걸 선정함

    const result = Object.entries(countObj).filter(([_, count]) => {
      return count === max;
    });
  
    const [key] = result[0];
 
    return result.length > 1 ? -1 : key;
  }

  const arr = [1, 2, 3, 3, 4, 4]
  console.log(maxNumber(arr))


> countObj 에 1 가 들어갔더니 1의 갯수는 1 가 되었음. countObj 는 {"1":1}

> countObj 에 2 가 들어갔더니 2의 갯수는 1 가 되었음. countObj 는 {"1":1,"2":1}

> countObj 에 3 가 들어갔더니 3의 갯수는 1 가 되었음. countObj 는 {"1":1,"2":1,"3":1}

> countObj 에 3 가 들어갔더니 3의 갯수는 2 가 되었음. countObj 는 {"1":1,"2":1,"3":2}

> countObj 에 4 가 들어갔더니 4의 갯수는 1 가 되었음. countObj 는 {"1":1,"2":1,"3":2,"4":1}

> countObj 에 4 가 들어갔더니 4의 갯수는 2 가 되었음. countObj 는 {"1":1,"2":1,"3":2,"4":2}

What new did you learn?

  • array.forEach((key) => {} : 키값을 하나씩 꺼냄
  • . . . Object : 배열의 대괄호 [ ] 를 벗겨냄.
  • Object.entries(obj) : 키 속성 키와 값 쌍을 반환
    ex) Object.entries(countObj) : { '1': 1, '2': 1, '3': 2, '4': 2 } => [ [ '1', 1 ], [ '2', 1 ], [ '3', 2 ], [ '4', 2 ] ]
  • filter((조건을 줄 변수 선언) => {return 조건})
    ex) filter(([_, count]) => { return count === max; }) : 키, 값중에서 키는 상관없이 값만 어떤 조건을 주겠다는 뜻

On a lighter note

처음에 짱구를 굴려서 혼자 만들었던 코드도 최빈값을 구하는 코드가 아니라 최빈값의 총 횟수를 구하는 코드였음이 드러남

profile
sparkle

0개의 댓글