알고리즘 연습 진작 할 걸...
코딩 처음 배울 때가 생각난다.
프론트엔드 배우면서 웹사이트를 구축해가는 것이 재미있었다. 코딩으로 그림 그리는 기분.
프론트엔드도 코딩테스트 연습하면 좋다길래 들어간 프로그래머스에서 레벨1 코딩 테스트 맛보고 크게 좌절하였다.
무슨 동전 공장에 동전 별로 원자재값 알려주고 원가 어느 정도로 얼마만큼의 동전을 생산해야 하는데 100원은 몇 개 만들 수 있냐는 문제였다.
다시 기본부터 열심히 해보자
쓰면서 이게 어떤 원리로 작동하는 지 몰랐던 것들은 원리를 코드로 설명하기 위해 정리
아니면 정말 몰랐던 것들 정리
고차 함수는 자신의 파라미터에 함수를 전달 받는 것을 뜻한다.
for문을 대체하기 위한 고차함수
포인트는 배열을 단순 순회하면서 callback 함수를 계속 호출
forEach 문은 이런 식으로 동작한다.
function forEach(predicate, thisArg){
for(let i =0; i< arr.length; i++){
predicate(arr[i], i, arr)
}
}
thisArg는 callback 실행될 때, this로 사용하는 값
실행하면 이렇게 된다.
arr.forEach(function(val, idx, array){
console.log(val, idx, array, this)
},[0,1])
//** 결과값
// arr[i], i, [...arr], [0,1]
그런데 신기한 것은 화살함수(arrowFunc)을 사용하면 thisArg을 window 객체로 출력한다.
arr.forEach((val, idx, array) => {
console.log(val, idx, array, this);
}, [1, 2]);
//** 결과값
// arr[i], i, [...arr], Window{}
이유는 화살표 함수는 this 바인딩을 렉시컬(lexical)하게 처리하기 때문.
즉, 화살표 함수 내에서의 this는 함수가 정의된 외부 스코프의 this를 그대로 사용하기 때문이며 위 같은 경우 외부 스코프가 전역 객체이며 브라우저 환경에 경우 Window를 객체를 사용한다.
forEach와 마찬가지로 배열의 값들을 순회하지만 callback 함수에서 반환된 값으로 새로운 배열을 반환한다.
코드로 설명하면 이렇다.
function map(predicate, thisArg){
let answer = [];
for(let i =0; i< arr.length; i++){
answer.push(predicate(arr[i], i, arr));
}
return answer; // 새로운 Array를 return
}
find는 조건에 맞는 값 하나만 return한다. 정확히는 callback의 반환값이 true인 첫번째 반환
function find(predicate, thisArg){
let answer;
for(let i =0; i< arr.length; i++){
if(predicate(arr[i], i, arr) === true){
answer = arr[i];
break;
}
}
return answer
}
find에서 나온 값의 index 값을 반환
function findIndex(predicate, thisArg){
let answer;
for(let i =0; i< arr.length; i++){
if(predicate(arr[i], i, arr) === true){
answer = i
break;
}
}
return answer
}
나는 실무에서 map 다음으로 제일 많이 쓴 것 같다.
callback 함수의 반환값이 true인 경우만 모아 새로운 배열을 만들어 반환
function filter(predicate, thisArg){
let answer = [];
for(let i =0; i< arr.length; i++){
if(predicate(arr[i], i, arr) === true){
answer.push(arr[i])
}
}
return answer
}
callback 함수의 반환값을 전달받아 계속 순회하면서 하나의 결과를 반환
개념은 이해가 되는데 원리는 살짝 어려운 느낌이다.
그래도 코드로 한번 풀어보자.
function reduce(predicate, initialValue){
let answer = initialValue || arr[0]; // init 값이 없으면 배열의 첫번째 설정
for(let i =0; i< arr.length; i++){
answer = predicate(answer, arr[i])
}
return answer
}
reduce는 설정값(initialValue)에 따라 다양하게 사용이 가능하다.
//reuce를 이용한 filter
const arr = [1,2,3,4,5]
console.log(arr.reduce(function (a, c) {
if (c > 2) {
a.push(c) //참고: return a.push(c); 하면 배열이 아니라 length가 반환된다.
return a;
}
}, []));
//** 출력값
// [3,4,5]
// reduce를 사용한 map
console.log(arr.reduce(function (a, c) {
a.push(c * 10)
return a;
}, []));
//** 출력값
// [10,20,30,40,50]
// 객체로 뽑아내기
const arr = [1, 2, 2, 3, 4, 4, 4, 5];
const result = arr.reduce(
(acc, currentValue) => {
// 중복되지 않은 요소만 추가
if (!acc.uniqueArray.includes(currentValue)) {
acc.uniqueArray.push(currentValue);
}
// 요소의 출현 횟수 세기
if (acc.elementCounts[currentValue]) {
acc.elementCounts[currentValue] += 1;
} else {
acc.elementCounts[currentValue] = 1;
}
return acc;
},
{ uniqueArray: [], elementCounts: {} }
);
console.log(result);
//* 출력:
//{
// uniqueArray: [1, 2, 3, 4, 5],
// elementCounts: {
// '1': 1,
// '2': 2,
// '3': 1,
// '4': 3,
// '5': 1
// }
//}
*/
가끔 cs 문제로 나온다고 한다.
코딩 배울땐 이렇게 있구나 정도로만 배웠던것 같다.
javascript에서는 x.charCodeAt() 이렇게 사용
알파벳 대분자는 64~90, 소문자는 97~122로 사용한다고 한다.