for문으로 돌릴 만한 부분을 모두 고차함수로 실행했다.
hash 객체에 key가 없으면 0으로 초기화해서 생성하고 있으면 1씩 더했다.
completion은 완주한 사람들이니 hash에서 다시 제외한다.
마지막으로 참가자를 다시 돌면서 (빼줬는데도) 아직까지 남아있는 사람들은 완주하지 못한 사람으로 보고 answer에 넣어 반환한다.
점수는 4점이 떴고 예측되는 문제는 participant를 2번 돌았다는 점, answer 변수를 선언하지 않고 바로 반환할 수 있을 것 같다는 점이었다. (마지막 forEach문에서 answer = person 대신 return person을 하면 오류가 났다)
function solution(participant, completion) {
let answer = '';
const hash = {};
participant.forEach((person) => hash[person] ? hash[person]++ : hash[person] = 1);
completion.forEach((person) => hash[person]--);
participant.forEach((person) => {
if (hash[person] >= 1) answer = person;
})
return answer;
}
위의 공정(?)을 많이 줄였다.
우선 answer 변수가 따로 없고 find로 true 값을 찾은 것을 바로 반환한다.
dic은 아마 파이썬의 dictionary를 말하는 것 같다. (무슨 자료형이었는지는 까먹음) reduce를 활용해 obj의 초기값은 빈 객체({ })로 지정하고 누적하는 t(completion 배열에서 뽑은 값)를 obj의 key로 설정하여 객체에 key가 있으면 +1, 없으면 1로 지정하고 (컴마 뒤의) obj를 통째로 반환한다.
reduce문의 컴마 뒤의 obj의 의미
=> 원래 reduce문은 숫자 타입을 반환한다. 하지만 연산 뒤에 초기값 타입(객체)을 반환하면 숫자 타입이 아닌 해당 초기값을 반환한다.
=>, obj
를 빼고 console에 출력했더니 dic이 1이 나왔다. 하지만, obj
를 넣어 출력하면 { eden: 1, kiki: 1 } 식으로 reduce로 만들어진 객체가 출력됐다.
이후 함수의 return문에서 participant에서 find로 조건에 해당하는 첫 번째 값을 찾아 바로 반환하는데, 조건은 dic객체의 t번째 값이 존재하면(= 1 이상이면) 해당 t에서 1을 빼고 만약 dic[t]번째 값이 없으면(= 0이면) 해당 값을 완주하지 못한 선수로 반환한다.
0은 falsy 값으로 true/false 중 false로 간주한다.
function solution(participant, completion) {
let dic = completion.reduce((obj, t)=> (obj[t]= obj[t] ? obj[t]+1 : 1 , obj) ,{});
return participant.find(t=> {
if(dic[t])
dic[t] = dic[t]-1;
else
return true;
});
}
reduce로 객체 반환하기와 find의 새로운 활용도를 느낄 수 있는 문제였다.