.map()
인자값: currenValue, index, array 요소를 일괄적으로 변경
var arr = ['foo', 'hello', 'diamond', 'A']
var arr2 = arr.map((v) => v.length) // 각 요소의 글자 길이값 반환
console.log(arr2) // [3, 5, 7, 1]
.filter()
요소를 걸러내어 배열로 true/false 반환, 없으면 빈 배열
var arr = [4, 15, 377, 395, 400, 1024, 3000]
var arr2 = arr.filter((v) => (v % 5 === 0))
console.log(arr2) // [15, 395, 400, 3000]
.find()
단 하나의 요소만 반환, 여러 개 있으면 처음값만 반환
let arr = [4, 15, 377, 395, 400, 1024, 3000]
let arr2 = arr.find((n) => (n % 5 === 0))
console.log(arr2) // 15
.reduce()
- callback
accumulator: 이전 마지막 콜백 호출에서 반환된 값 또는 공급된 경우 initialValue
currentValue: 배열 내 현재 처리되고 있는 요소(element)
currentIndex: 배열 내 현재 처리되고 있는 요소의 인덱스
array: reduce에 호출되는 배열
- initialValue
선택사항, callback의 첫 호출에 첫 번째 인수로 사용하는 값
let arr = [9, 2, 8, 5, 7]
let sum = arr.reduce((acc, val) => pre + val)
console.log(sum) // 31
// map
var arr = ['foo', 'hello', 'diamond', 'A']
var arr2 = arr.reduce((acc, value) => {
acc.push(value.length)
return pre
}, [])
console.log(arr2) // [3, 5, 7, 1]
// filter
var arr = [4, 15, 377, 395, 400, 1024, 3000]
var arr2 = arr.reduce((acc, value) => {
if (value % 5 == 0) {
acc.push(value);
}
return acc;
}, []);
console.log(arr2) // [15, 395, 400, 3000]
// find
var arr = [4, 15, 377, 395, 400, 1024, 3000]
var arr2 = arr.reduce((pre, value) => {
if (typeof pre == 'undefined' && value % 5 == 0) {
pre = value;
}
return pre;
}, undefined);
console.log(arr2) // 15
reduce()는 위의 map, find, filter 대체 가능합니다.
reduce vs. map
var data = [1, 2, 3];
var initialValue = [];
var reducer = function(accumulator, value) {
accumulator.push(value * 2);
return accumulator;
};
var result = data.reduce(reducer, initialValue);
console.log(result); // [2, 4, 6]
// map()
var result2 = data.map(x => x * 2);
console.log(result2); // [2, 4, 6]
map 코드가 훨씬 짧고 직관적
reduce vs. filter
var data = [1, 2, 3, 4, 5, 6];
var initialValue = [];
var reducer = function(accumulator, value) {
if (value % 2 != 0) {
accumulator.push(value);
}
return accumulator;
};
var result1 = data.reduce(reducer, initialValue);
console.log(result1); // [1, 3, 5]
// filter
var result2 = data.filter(x => x % 2 != 0);
console.log(result2); // [1, 3, 5]
filter 역시 코드가 더 직관적
reduce vs. filter + map
var data = [1, 2, 3, 4, 5, 6];
var initialValue = [];
var reducer = function(accumulator, value) {
if (value % 2 != 0) {
accumulator.push(value * 2);
}
return accumulator;
}
var result1 = data.reduce(reducer, initialValue);
console.log(result1); // [2, 6, 10]
// filter + map
var result2 = data.filter(x => x % 2 != 0).map(x => x * 2);
console.log(result2); // [2, 6, 10]
하지만, map과 filter를 동시에 작업해야 한다면 reduce 는 배열을 1번만 순회하면 되지만 filter/map 조합은 두 번 순회합니다.데이터 크기, 종류에 맞는 고려 및 결정이 필요해보입니다.
filter/map 이 개인적으로 훨씬 더 직관적인 것으로 보이지만, reducer라는 함수로 로직이 따로 빠져있는 reduce가 더 재사용성이 좋아보입니다.
평균 구하기
var data = [1, 2, 3, 4, 5, 6, 1];
var reducer = (accumulator, value, index, array) => {
var sumOfAccAndVal = accumulator + value;
if (index === array.length - 1) {
return (sumOfAccAndVal) / array.length;
}
return sumOfAccAndVal;
};
var getMean = data.reduce(reducer, 0);
console.log(getMean); // 3.142857142857143
accumulator 와 value 를 더해서 sum 을 만들고, 끝에 가서 배열의 크기로 나누는 로직입니다.
이때 초기값(initial value)을 0으로 셋팅했는데, 적지 않아도 됩니다. 그러면, 첫 번째 인자인 1 (data[0])이 accumulator로 넘어갑니다.
initial value 주의하기
const data = ["vote1", "vote2", "vote1", "vote2", "vote2"];
const reducer = (accumulator, value, index, array) => {
if (accumulator[value]) {
accumulator[value] = accumulator[value] + 1;
} else {
accumulator[value] = 1;
}
return accumulator;
};
const getVote = data.reduce(reducer, {}); // { vote1: 2, vote2: 3 }
const getVote2 = data.reduce(reducer); // "vote1"
initial value 가 있고 없음에 따라 큰 차이가 나는 getVote, getVote2 를 비교한 코드입니다. getVote2 는 왜 예상과 다른 결과가 나온 이유는 reduce 메서드의 두 번째 인자로 아무 값도 전달이 되지 않았기 때문입니다.
배열의 첫 번째 값, "vote1" 이 첫 번째 순회의 accumulator 로 전달되었고, 조건문의 조건이 "vote1"["vote2"] 이 되면서 결과는 undefined(false)가 되어 "vote1"["vote"] = 1; 이라는 의미없는 로직을 한 번 타고, 결론적으로 다음 accumulator 로 또 "vote1" 이라는 string 을 넘기게 된 것입니다.
flattenMap
const input = [
{
"title": "슈퍼맨",
"year": "2005",
"cast": ["장동건", "권상우", "이동욱", "차승원"]
},
{
"title": "스타워즈",
"year": "2013",
"cast": ["차승원", "신해균", "장동건", "김수현"]
},
{
"title": "고질라",
"year": "1997",
"cast": []
}
];
const flatMapReducer = (accumulator, value, index, array) => {
const key = "cast";
if (value.hasOwnProperty(key) && Array.isArray(value[key])) {
value[key].forEach(val => {
if (accumulator.indexOf(val) === -1) {
accumulator.push(val);
}
});
}
return accumulator;
};
const flattenCastArray = input.reduce(flatMapReducer, []);
// ['장동건', '권상우', '이동욱', '차승원', '신해균', '김수현']
배열을 순회하면서 배열의 값으로 들어있는 object 의 key 존재여부를 확인하고, unique 한 "cast"를 key 로 갖는 배열의 값들을 최종적으로 return 합니다.
reduceRight
const data = [1, 2, 3, 4, "5"];
const sumData1 = data.reduce((accumulator, value) => {
return accumulator + value;
}, 0);
console.log(sumData1); // "105"
// reduceRight
const sumData2 = data.reduceRight((accumulator, value) => {
return accumulator + value;
}, 0);
console.log(sumData2); // "054321"
sumData1은 0 부터 4까지 더해짐으로써 10이 되었고 마지막에 문자 "5" 와 합하게 되면서 "105" 가 return
reduceRight는 배열의 끝(오른쪽)부터 순회를 시작하는의 값, 즉 sumData2은 0 과 문자 "5" 가 첫 순회 때 + 되면서 "05" 가 되고 계속해서 string 이 더해져 "054321"을 출력합니다.
reduce 함수형 프로그래밍
const increment = (input) => { return input + 1; };
const decrement = (input) => { return input - 1; };
const double = (input) => { return input * 2; };
const halve = (input) => { return input / 2 };
const initial_value = 1;
// 1. 일반적일 수 있는 로직
const incremented_value = increment(initial_value);
const doubled_value = double(incremented_value);
const final_value = decrement(doubled_value);
console.log(final_value); // 3
// 2. reduce 를 활용한 함수형 프로그래밍
const pipeline = [
increment,
double,
decrement,
decrement,
decrement,
halve,
double,
];
const final_value2 = pipeline.reduce((accumulator, func) => {
return func(accumulator);
}, initial_value);
console.log(final_value2); // 1
'Javascript' 카테고리의 다른 글
모바일에서 레이어 팝업 띄우고 본문 스크롤 안되게 막기 (0) | 2013.12.20 |
---|---|
Javascript event.keyCode (0) | 2013.11.22 |
터치 이미지 슬라이드 관련 참고 자료 (0) | 2013.11.20 |
javascript 변수 값 비교 하기 (===, !== 차이) (0) | 2013.11.13 |
조건 연산자 ?, : (0) | 2013.11.13 |
개의 댓글