💡 이 포스트에는 S2 Unit 1. javascript 고차함수 - map, filter, reduce 등과 관련된 코딩과제를 하고 몰랐던 점이나 부족했던 점을 정리했다!
(누군가에게는 너무 쉬워 하품이 나올 수 있습니다.🥲)
이번에는 고차함수 중 콜백함수의 사용법과 내장된 고차함수 메서드인 map, filter, reduce를 실습할 수 있는 코딩문제를 풀었다.
문제를 풀며 막혔던 내용, 새로 발견한 내용 등을 정리해 보았다.
핵심 : 어떤 값 n보다 작은 값들의 개수에 1을 더하면 n의 순서가 된다.
핵심 : 배열이면, 어떤 값 n보다 작은 값들의 개수가 n의 순서가 된다.
위 핵심의 원리로 보다 작은 값만 판별할 수 있다면 배열을 정렬하지 않고도 어떤 값 n의 순서를 구할 수 있다.
map을 사용하는 방법이 있고, reduce를 사용하는 방법이 있다.
let arr=[3,1,4]; //
let n=2;
//방법1 map : index가 따로 필요
function code01(n){
let index=0; //순서
arr.map((el)=>{
if(el<n) index+=1;
});
return index;
}
//방법2 reduce
function code02(n){
return arr.filter((el)=>{
return el < n;
}).length; //filter가 리턴하는 값의 길이를 리턴
}
code01(n); //
code02(n); //
핵심 : 조건문 사용시 if(n!==0)과 if(n)은 같다.
이 내용은 고차함수와는 큰 연관이 없지만 코딩문제를 풀 때 자주 나오기도 했고, 놓치면 안될 내용이라 작성했다.
if(n)은 값의 존재여부를 떠나 0이 아닐 때도 활용 가능하다. 0은 falsy값이지만 0이 아닌 숫자는 truthy값이기 때문이다.
이 원리를 이용하여 if(n%2!==0)와 if(n%2)도 같은 의미라 할 수 있다.
핵심 : 총합은 reduce로 간편하게 구할 수 있다.
어떤 배열의 총합을 구해 배열의 길이로 나누면 된다.
빈 배열의 예외가 있을 경우 먼저 조건문으로 예외 처리한다.
간단히 작성할 수 있는 코드이지만, 2번의 내용과 화살표 함수를 이용해 나의 코드를 리팩토링 해보았다.
let myArr=[1,2,3,4];
//빈 배열은 'no value!'를 리턴할 것
//이전 코드
function lookForAverageBefore(arr){
if(arr.length===0) return 'no value!';
let sum=arr.reduce(function(sum, cur){
return sum+cur;
});
return sum/arr.length;
}
//리팩토링한 코드
function lookForAverageAfter(arr){
let len=arr.length;
if(!len) return 'no value!'; //falsy값 활용
return arr.reduce((acc, cur)=>acc+cur)/len; //화살표 함수 사용
}
lookForAverageBefore(myArr); //2.5
lookForAverageAfter(myArr); //2.5
핵심 : 배열에서 조건에 맞는 값만 더하려면 filter 후 reduce하거나, reduce 할 때 조건을 거는 방법이 있다.
나는 filter로 조건에 맞는 값만 추려서 reduce로 총합을 구했으나,
reduce 안에서 조건을 걸어 해당하는 값만 더하는 방법이 있다.
다만 조건에 맞지 않는 값일 때는 반드시 그냥 누산값을 리턴해줘야 한다.
arr=[1,2,3,4,5,6];
//짝수만 더하기
//방법1
function evenSum01(arr){
let evenArr=arr.filter(el=> el%2===0);
return evenArr.reduce((acc,cur)=> acc+cur,0);
}
//방법2
function evenSum02(arr){
return arr.reduce((acc,cur)=>{
if(cur%2===0){
return acc+cur;
}else{
return acc;//조건에 맞지 않는 값은 더하지 않음
}
}, 0);
}
핵심 : reduce와 조건문을 사용해 가장 큰 값을 찾는다.
핵심 : 비교시 정하는 첫 값은 누산값으로 정하고, 현재값이 큰 경우 현재값으로 대체한다.
최대값, 최소값 등등......
비교할 때 원리는
이 원리를 이용해 reduce에 적용하자면,
let arr=[1,9,9,2,5];
let index=0;
function findBiggest(arr){
//reduce는 콜백함수의 3번째 매개변수로 현재 요소의 인덱스를 전달한다.
let result= arr.reduce((a, b, curIdx)=>{
if(a < b){ //조건
index=curIdx;
return b;
}else{
return a;
}
});
return `가장 큰 값은 ${result}, 이 값의 인덱스는 ${index}`;
}
//조건이 a<b일 경우
findBiggest(arr); //'가장 큰 값은 9, 이 값의 인덱스는 1'
//만약 조건이 a<=b일 경우
//findBiggest(arr); //'가장 큰 값은 9, 이 값의 인덱스는 2'
위 예제에서 reduce안의 조건이 a<b인 경우에는 1번째 인덱스의 값을 제일 큰 값으로 가져오지만,
a<=b인 경우에는 2번째 인덱스의 값을 제일 큰 값으로 가져오니 주의한다.
reduce의 작동방식을 잘 알아야 문제푸는 데 지장이 없다!
아래의 링크에서 #reduce 작동방식을 보면 이해가 쉽다.
javascript MDN - Array.prototype.reduce()
핵심 : reduce식을 작성할 때 초기값은 리턴하고자 하는 값의 type에 따라 맞춘다.
필요에 따라
문자열을 리턴해야할 때는 초기값을 '',
숫자를 리턴해야할 때는 0을,
배열을 리턴해야할 때는 []을 초기값으로 설정한다.
핵심 : 배열의 요소 중 가장 길거나 짧은 길이를 구해야 한다면 reduce를 사용한다.
핵심 : 배열의 요소가 문자열 또는 배열인 경우, 길이를 구해야 한다면 값 자체를 구한 뒤 length를 구한다.
reduce를 사용할 때 조회하는 누산값, 현재값은 값 자체를 다룬다.
만약 값의 길이를 구해야 한다면 값 자체를 구한 뒤 나중에 length를 덧붙이는 것이 좋다.
//가장 짧은 문자열의 길이 구하기
let arr=['s2', 'unit1', 'javascript', '고차함수'];
function shortestWord(arr){
return arr.reduce((acc, cur)=>{
if(acc.length > cur.length){
return cur;
}else{
return acc;
}
}).length;
//.length 부분을 제외하면 문자열 자체('s2')가 리턴된다.
//그러므로 길이를 구하려면 's2'.length 가 필요하다.
}
shortestWord(arr);
핵심 : 배열이 주어졌을 때, 원하는 값을 한 번에 구하지 말고 나눠서 구한다.
핵심 : 조건에 맞는 배열을 먼저 filter로 구한다.
핵심 : 최대값, 최소값, 총합, 평균 등을 구할 때 reduce를 사용한다.
핵심 : 배열을 변경해야 할 경우 map을 사용한다.
신경써야할 내용이 많지만 한꺼번에 생각하려 하지않고 나눠서 생각하면 값을 구하기가 좀 더 쉬웠다.
만약 조건을 만족하는 값 중 최대값을 구해야 한다면 한꺼번에 구하기보다
이런 방법으로 나눠서 생각한 뒤
이렇게 해당하는 메서드를 사용해 문제를 풀어나갈 수 있다.
//짝수 중 가장 큰 값 구해서 배열 바꾸기
let arr=[1,3,4,5,8];
function changeBiggestEven(arr){
//짝수 중 -> 짝수 구하기
let arrEven=arr.filter((el) => el%2===0);
//가장 큰 값 구하기
let biggestEven=arrEven.reduce((acc,cur) =>{
if(acc < cur){
return cur;
}else{
return acc;
}
});
//가장 큰 값으로 배열 교체하기
return arr.map((el)=> biggestEven);
};
changeBiggestEven(arr); //[8,8,8,8,8]
cf. 더 복잡한 경우
만약 각 요소 안에 중첩된 배열 또는 객체가 있을 경우
정리하자면 map으로 각 요소를,
map메서드를 사용하고, 그 내부에서 중첩된 요소들의 계산을 reduce로 구해 리턴한다. 그러면 map 안에 reduce가 중첩된 형태가 된다.
콜백함수는 다른 문법에 비해 많이 어색했다. 그러다 계속 작성하니까 좀 더 사용이 익숙해졌는데 참 다행이었다. map, filter 메서드는 사용하는 데 큰 무리가 없었지만 아무래도 reduce의 개념과 이를 활용한 코딩문제는 막상 마주해서 푸니까 자꾸 헷갈리고 쉽지 않았다.
그래서 하나하나 콘솔 창에서 콘솔로 띄워보고 연구했다. 그리고 관련 MDN 문서도 읽다보니 점점 이런? 코딩문제 풀기의 상황에 익숙해져 가고 있다.
이번의 부족한 점
부족한 점 보완하기
😌