완주하지 못한 선수

WooBuntu·2020년 7월 24일
0

완주하지 못한 선수

2020.07.24

// 클린코드의 규칙에 따라 부정조건문을 쓰지 않고,
// 조건문을 캡슐화하기 위해 따로 뺀 함수이다.
const shouldInitProp = (obj, prop) => {
  return !obj.hasOwnProperty(prop);
};

const convertToHash = (arr) => {
  const hashTable = {};
  for (let item of arr) {
    // 클린코드에서 조건문은 최대한 쓰지 말라고 했고,
    // 조건문을 쓸 경우에는 캡슐화를 하라고 했다.
    // 여기서 조건문을 어떻게 뺄 수 있을까...
    if (shouldInitProp(hashTable, item)) {
      hashTable[item] = 1;
    } else {
      hashTable[item]++;
    }
  }
  return hashTable;
};

const solution = (participant, completion) => {
  const hashOfParticipant = convertToHash(participant);
  for (const name of completion) {
    hashOfParticipant[name]--;
    // 값이 1인 프로퍼티를 다시 순회하면서 찾지 않기 위해
    // 값이 0이 된 프로퍼티는 즉시 삭제
    if (hashOfParticipant[name] == 0) {
      delete hashOfParticipant[name];
    }
  }

  // 마지막에는 객체에 프로퍼티가 하나만 남아있을 것이므로
  // 그대로 반환
  return Object.keys(hashOfParticipant)[0];
};
  • 다른 사람의 풀이 중에 내 풀이보다 효율성이 높은 풀이가 하나 있었는데 내 convertToHash함수를 reduce함수 한 줄로 대체해버린 코드였다.
    (그놈의 reduce)

  • 그런데 클린 코드에서 삼항 연산자에 대한 언급이 없는데, 이 역시 조건문이니 최대한 지양해야 하는 걸까

  • 개선할 점을 고려한 결과 수정한 코드는 다음과 같다.

// 클린코드의 규칙에 따라 부정조건문을 쓰지 않고,
// 조건문을 캡슐화하기 위해 따로 뺀 함수이다.
const shouldInitProp = (obj, prop) => {
  return !obj.hasOwnProperty(prop);
};

// reducer함수이다.
// 초기 값으로 {}(객체 리터럴)을 전달하기 때문에
// 맨 처음 받게 되는 인자는 hash:{}, item:배열의 첫 번째 원소이다.
const convertToHash = (hash, item) => {
  if (shouldInitProp(hash, item)) {
    hash[item] = 1;
  } else {
    hash[item]++;
  }
  return hash;
};

const getAnswer = (name, obj) => {
  // participant에 있는데 completion에 없다면 반환
  // completion에 프로퍼티로 있지만 그 값이 0인 경우에도 반환
  // (동명이인으로써 이미 --연산자를 거쳤다는 것이므로)
  if (obj[name]) {
    obj[name]--;
  } else {
    return true;
  }
};

const solution = (participant, completion) => {
  const hashOfCompletion = completion.reduce(convertToHash, {});
  return participant.find((name) => getAnswer(name, hashOfCompletion));
};
  • 일단 기존의 내 코드는 participant를 해쉬로 만들고 completion을 순회하면서 해쉬의 값을 차감하였다.

  • 그 결과 남은 프로퍼티(값이 1인)를 반환하고자 한 것이다.

  • 그런데 이렇게 하면 결국 completion을 전부 순회해야만 했다.

  • 기준을 바꿔 completion을 해쉬로 만들고 participant로 순회를 돌면, 해쉬에 값이 없거나 값이 0인(동명이인으로 이미 차감된) 프로퍼티를 찾는 순간 순회를 끝까지 돌 필요가 없다.

  • 그리고 reduce와 find등의 메소드를 쓰는 함수형 프로그래밍이 클린 코드의 관점에서도 더욱 바람직하다고 한다.

2020.09.12

function solution(participant, completion) {
  const hash = {};
  for (const name of completion) {
    if (!hash.hasOwnProperty(name)) {
      hash[name] = 1;
    } else {
      hash[name]++;
    }
  }
  for (const name of participant) {
    if (!hash.hasOwnProperty(name)) {
      return name;
    }
    hash[name]--;
    if (hash[name] == 0) {
      delete hash[name];
    }
  }
}

0개의 댓글