JS레플릿 30.object(3)_10.20

송철진·2022년 10월 20일
0

Assignment

아래 설명을 읽고 getExamResult 함수를 구현하세요.
인자 scores 는 다음과 같은 객체입니다. 객체의 요소의 갯수 및 키의 이름들은 달라질 수 있습니다. 객체의 값은 다음 9가지 문자열 중에서 하나를 가지고 있습니다.

'A+', 'A', 'B+', 'B', 'C+', 'C', 'D+', 'D', 'F'
{
  '생활속의회계': 'C',
  '논리적글쓰기': 'B',
  '독일문화의이해': 'B+',
  '기초수학': 'D+',
  '영어회화': 'C+',
  '인지발달심리학': 'A+',
}

인자 requiredClasses 는 다음과 같이 문자열로 된 배열입니다.
['영어회화', '기초수학', '공학수학', '컴퓨터과학개론']
다음 조건을 만족하는 객체를 리턴하도록 함수를 구현해주세요.
scores 객체가 가지고 있는 키들은 새로운 객체에 포함되어야 합니다. 단, 그 값들은 다음 원리에 따라 숫자로 바뀌어 할당되어야 합니다.

A+ => 4.5
A => 4
B+ => 3.5
B => 3
C+ => 2.5
C => 2
D+ => 1.5
D => 1
F => 0

requiredClasses 배열의 요소로는 존재하지만, scores의 키로는 존재하지 않는 항목이 있다면, 해당 요소는 새로운 객체의 키가 되고, 값으로 0을 가져야 합니다. 위에서 예시로 묘사된 객체와 배열이 인자로 들어왔다면, 다음과 같은 객체과 리턴됩니다. 요소간 순서는 다를수 있지만, 채점에 무관합니다.

{
  '생활속의회계': 2,
  '논리적글쓰기': 3,
  '독일문화의이해': 3.5,
  '기초수학': 1.5,
  '영어회화': 2.5,
  '인지발달심리학': 4.5,
  '공학수학': 0,
  '컴퓨터과학개론': 0,
}
const getExamResult = (scores, requiredClasses) => {

  for (let key in scores) {
    const value = socres[key]
    const numericScores = 
  }
  
}

로직 생각해보기

  1. 객체scores의 '학점(값)'을 상수 value에 할당, 그 value를 학점을 숫자로 변환하는 함수 getNum()에 넣는다.
const getExamResult = (scores, requiredClasses) => {
  const value = scores[key];
  getNum(value);  
}  
  1. 함수 getNum()로부터 리턴된 숫자는 상수 numericScores에 할당, 객체scores의 값으로 재할당한다.
const getExamResult = (scores, requiredClasses) => {
  
    const value = scores[key];
    const numericScores = getNum(value);
    scores[key] = numericScores;
  
}  
  1. 1-2.를 객체 순회한다
const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key];
    const numericScores = getNum(value);
    scores[key] = numericScores;
  }
}  
  1. scores의 키를 뽑아 배열arrayKey로 선언한다.
    기존 과목(scores의 키)에 추가할 과목(requiredClasses의 값)이 있는지 비교하는데 쓸 것이다.
const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key];
    const numericScores = getNum(value);
    scores[key] = numericScores;
  }
  const arrayKey = Object.keys(scores);
}  
  1. 배열requiredClasses의 '값'이 배열arrayKey의 '값'에 존재하지 않으면 기존 과목(scores의 키)에 추가할 과목(requiredClasses의 값)이 없으면 객체scores에 '키': 배열requiredClasses의 값, '값': 0으로 추가한다.
const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key];
    const numericScores = getNum(value);
    scores[key] = numericScores;
  }
  const arrayKey = Object.keys(scores);
  
  if(!arrayKey.includes(requiredClasses[i]){
    scores[requiredClasses[i]] = 0;
  }
}  
  1. 5.를 객체순회한다.
const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key];
    const numericScores = getNum(value);
    scores[key] = numericScores;
  }
  const arrayKey = Object.keys(scores);
  for(let i in requiredClasses){
    if(!arrayKey.includes(requiredClasses[i]){
      scores[requiredClasses[i]] = 0;
    }
  }
}
  1. scores를 리턴한다
const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key];
    const numericScores = getNum(value);
    scores[key] = numericScores;
  }
  const arrayKey = Object.keys(scores);
  for(let i in requiredClasses){
    if(!arrayKey.includes(requiredClasses[i]){
      scores[requiredClasses[i]] = 0;
    }
  }
  return scores;
}  

결과

const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key]; 
    const numericScores = getNum(value);
    scores[key] = numericScores;
  }
  const arrayKey = Object.keys(scores);
  for(let i in requiredClasses){
    if(!arrayKey.includes(requiredClasses[i])){
      scores[requiredClasses[i]] = 0;
    }
  }
  return scores;
}

const getNum = x => {
  switch(x) {
    case 'A+':
      return 4.5;
      break;
    case 'A':
      return 4;
      break;
    case 'B+':
      return 3.5;
      break;
    case 'B':
      return 3;
      break;
    case 'C+':
      return 2.5;
      break;
    case 'C':
      return 2;
      break;
    case 'D+':
      return 1.5;
      break;
    case 'D':
      return 1;
      break;
    case 'F':
    default:
      return 0;
      break;
  }  
}

const a = {
  '생활속의회계': 'C',
  '논리적글쓰기': 'B',
  '독일문화의이해': 'B+',
  '기초수학': 'D+',
  '영어회화': 'C+',
  '인지발달심리학': 'A+',
};
const b = ['영어회화', '기초수학', '공학수학', '컴퓨터과학개론'];
console.log(getExamResult(a,b));

다른 풀이

👉 링크

Today I Learn

1. 객체의 키를 변수로 접근하기

다음 객체에서 상수verb의 값을 키로, 상수project의 값을 그 키의 값으로 사용하시오

const information = {
  name: '김개발'
}
const verb = 'developes'
const project = 'facebook'

👉

information.developes = 'facebook' // 항상 값이 정해져 있음
information[verb] = project // verb, project의 값에 따라 달라짐

2. 객체 순회하기

객체에 있는 모든 키에 한번씩 접근하는 방법

2-1. Object.keys()

어떤 객체가 가지고 있는 키들의 목록을 배열로 리턴하는 메소드

예)

const obj = {
  name: 'melon',
  weight: 4350,
  price: 16500,
  isFresh: true
}
Object.keys(obj) // ['name', 'weight', 'price', 'isFresh']

Object.values : 객체의 값으로 이루어진 배열을 리턴
Object.entries : 객체의 키-값 쌍인 길이 2짜리 배열로 이루어진, 배열을 리턴
(인덱스[0]: 키, 인덱스[1]: 값)

Object.entries 가 가장 유용하다!

2-2. for-in

객체와 배열을 위해 특별히 존재하는, ES6 에서 추가된 문법

배열: 기존의 for문을 간소화

/*
for (let i = 0; i < arr.length; i ++) {
  console.log(i)
  console.log(arr[i])
}
*/
for (let i in arr) {
  console.log(i)
  console.log(arr[i])
}

객체: 순서가 보장되지 않는 순회

for (let key in obj) {
  const value = obj[key]

  console.log(key)
  console.log(value)
}

다른 풀이#1

const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key]; 
    const numericScores = {
      'A+': 4.5,
      'A': 4.0,
      'B+': 3.5,
      'B': 3.0,
      'C+': 2.5,
      'C': 2.0,
      'D+': 1.5,
      'D': 1.0,
      'F': 0      
    }
    scores[key] = numericScores[value];
  } 
  for(let el of requiredClasses){
    if(!Object.keys(scores).includes(el)){
      scores[el] = 0;
    }  
  }
  return scores;
}

const scores = {
  '생활속의회계': 'C',
  '논리적글쓰기': 'B',
  '독일문화의이해': 'B+',
  '기초수학': 'D+',
  '영어회화': 'C+',
  '인지발달심리학': 'A+',
};
const requiredClasses = ['영어회화', '기초수학', '공학수학', '컴퓨터과학개론'];
console.log(getExamResult(scores,requiredClasses));

로직 생각해보기

  1. scores의 key에 대해 객체 순회하겠다
for(let key in scores){
  // 객체 순회 내용
}
  1. scores의 로 접근한 학점을 value라고 선언한다
// 객체 순회 내용1
const value = scores[key]; 
// ex) scores['생활속의회계'] === 'C' 이다
  1. 학점-점수 쌍을 갖는 객체numericScores를 선언한다
// 객체 순회 내용2
const numericScores = {
      'A+': 4.5,
      'A': 4.0,
      'B+': 3.5,
      'B': 3.0,
      'C+': 2.5,
      'C': 2.0,
      'D+': 1.5,
      'D': 1.0,
      'F': 0      
    }
  1. scores의 학점이 numericScores의 학점와 일치하면
    scores의 학점을 numericScores의 점수으로 재할당한다.
    👉
    scores의 학점을 ==> value
    numericScores의 로 넣고 접근한 점수 ==> numericScores[value]
    scores의 key로 접근한 학점에 ==> scores[key]
    재할당하면
// 객체 순회 내용3
scores[key] = numericScores[value];
// ex) scores['생활속의회계'] = numericScores['C+']
  1. 배열requiredClasses의 요소el에 대해 객체 순회하겠다
for(let el of requiredClasses){
  // 객체 순회 내용
}
  1. scores의 키만 뽑은 배열에서 ==> Object.keys(scores)
    요소el을 포함하지 않으면 ==> !Object.keys(scores).includes(el)
    scores에 키el-값0을 추가하겠다 ==> scores[el] =0;
//객체 순회 내용
if(!Object.keys(scores).includes(el)){
  scores[el] = 0;
}  

참고로 for...in구문을 쓰면 index로 접근해야 한다:

for(let i in requiredClasses){
  if(!Object.keys(scores).includes(requiredClasses[i])){
    scores[requiredClasses[i]] = 0;
  }
}

다른 풀이#2

const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key];
    const numericScores = x => {
      if(x === 'F'){ 
        return x = 0;
      }else if(x.indexOf('+') === -1){
        return x = 69 - x.charCodeAt(0);
      }else{
        return x = 69 - x.charCodeAt(0) + 0.5;
      }
    }
    scores[key] = numericScores(value);
  }  
  let scoKey = Object.keys(scores);
  let scoValue = Object.values(scores);
  for(let ele of requiredClasses)
    if(!scoKey.includes(ele)){
      scoKey.push(ele);
      scoValue.push(0);
    }
  const scoresNew = {};
  for(let i in scoKey){
    scoresNew[scoKey[i]] = scoValue[i];
  }
  return scoresNew;
}
  
const a = {
  '생활속의회계': 'C',
  '논리적글쓰기': 'B',
  '독일문화의이해': 'B+',
  '기초수학': 'D+',
  '영어회화': 'C+',
  '인지발달심리학': 'A+',
};
const b = ['영어회화', '기초수학', '공학수학', '컴퓨터과학개론'];
console.log(getExamResult(a,b));

로직 생각해보기

  1. scores의 key에 대해 객체 순회하겠다
for(let key in scores){
  // 객체 순회 내용
}
  1. scores에서 key로 접근한 학점을 value라고 선언한다
// 객체 순회 내용#1
const value = scores[key];
  1. 학점을 인자x로 받아 숫자로 변환할 함수numericScores를 선언한다.
// 객체 순회 내용#2
const numericScores = x => {
}
  1. 알파벳을 숫자로 변환하는 메서드charCodeAt
    특정 문자열의 위치를 찾는 메서드indexOf를 이용한다
    (못 찾으면 -1 반환)

    string.charCodeAt(index)
    : 문자열string의 index번째 글자를 숫자로 반환한다
    ex) 'ABCDF'.charCodeAt(1) === 66

    A: 65 ==> 4 ==> 69 - 65 ==> 69 - 'A~'.charCodeAt(0)
    B: 66 ==> 3 ==> 69 - 66 ==> 69 - 'B~'.charCodeAt(0)
    C: 67 ==> 2 ==> 69 - 67 ==> 69 - 'C~'.charCodeAt(0)
    D: 68 ==> 1 ==> 69 - 68 ==> 69 - 'D~'.charCodeAt(0)
    F: 70 ==> 0

// 객체 순회 내용#2
const numericScores = x => { // 학점을 인자로 받아서
  if(x === 'F'){ // F면 0을 반환
    return x = 0;
  }else if(x.indexOf('+') === -1){ // F가 아니고 '+'가 없으면 
    return x = 69 - x.charCodeAt(0);
  }else{ // F가 아니고 '+'가 있으면 +0.5
    return x = 69 - x.charCodeAt(0) + 0.5;
  }
}

false인 값: -0, 0, null, undefined, Nan, false, ""을 활용해 바꿔쓸수도 있겠다. 근데 나중에 다시보기에 난해하니 별로 추천하지 않음

else if( !(x.indexOf('+')+1) ){ // F가 아니고 '+'가 없으면
}
  1. 함수numericScores에 scores의 학점인 value를 인자로 넣고
    ==> numericScores(value)
    그것을 key로 접근한 scores의
    ==>scores[key]
    재할당한다
// 객체 순회 내용#3
scores[key] = numericScores(value);
  1. 그렇게 값이 변환된 scores에 대하여
    만 뽑은 배열scoKey와 만 뽑은 배열 scoValue를 선언한다
  let scoKey = Object.keys(scores);
  let scoValue = Object.values(scores);
  1. 배열requiredClasses의 인자ele에 대해 객체 순회한다
  for(let ele of requiredClasses){
    // 객체 순회 내용
  }
  1. 인자ele이 scoKey에 포함되어있지 않다면 scoKey 오른쪽 끝에 인자el을 추가하고 scoValue 오른쪽 끝에 0을 추가한다
// 객체 순회 내용
if(!scoKey.includes(ele)){
  scoKey.push(ele);
  scoValue.push(0);
}
  1. 반환할 신규 객체scoresNew를 빈 상태로 생성하고
const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    // 객체 순회 내용#1
    // 객체 순회 내용#2
    // 객체 순회 내용#3
  }
  let scoKey = Object.keys(scores);
  let scoValue = Object.values(scores);
  for(let ele of requiredClasses){
    // 객체 순회 내용
  }
  const scoresNew = {};
  // 10. scoKey, scoValue 합치기
  return scoresNew;
}
  1. 배열scoKey의 i에 대하여 객체 순회로
    scoresNew에 scoKey[i] - scoValue[i]을 추가한다
for(let i in scoKey){
  scoresNew[scoKey[i]] = scoValue[i];
}

다른 풀이#3

const getExamResult = (scores, requiredClasses) => {
  for(let key in scores){
    const value = scores[key]; 
    const numericScores = {
      'A+': 4.5,
      'A': 4.0,
      'B+': 3.5,
      'B': 3.0,
      'C+': 2.5,
      'C': 2.0,
      'D+': 1.5,
      'D': 1.0,
      'F': 0      
    }
    scores[key] = numericScores[value];
  } 
  for(let el of requiredClasses){
    if(!scores[el]){ // 여기가 '다른 풀이#1'과 다른 부분
      scores[el] = 0;
    }  
  }
  return scores;
}

const scores = {
  '생활속의회계': 'C',
  '논리적글쓰기': 'B',
  '독일문화의이해': 'B+',
  '기초수학': 'D+',
  '영어회화': 'C+',
  '인지발달심리학': 'A+',
};
const requiredClasses = ['영어회화', '기초수학', '공학수학', '컴퓨터과학개론'];
console.log(getExamResult(scores,requiredClasses));

로직 생각해보기

배열requiredClasses의 요소el을
객체scores에 접근한 에 대해 ==> scores[el]
scores['공학수학'], scores['컴퓨터과학개론']은 추가되는 것이므로 undefined이다.
이 때, undefined는 false인 값에 해당하므로 다음과 같이 쓸 수 있다:

for(let el of requiredClasses){
    if(!scores[el]){ // 여기가 '다른 풀이#1'과 다른 부분
      scores[el] = 0;
    }  
  }

profile
검색하고 기록하며 학습하는 백엔드 개발자

0개의 댓글