이 답변을 작성하면서 영감을 받아 나중에 블로그 게시물을 확장하고 작성하여 자세히 설명했습니다. 이 문제에 대해 생각하는 방법에 대해 더 깊이 이해하고 싶다면 그것을 확인하는 것이 좋습니다. 나는 그것을 하나씩 설명하려고 노력하고 마지막에는 속도 고려 사항을 검토하면서 JSperf 비교를 제공합니다.
즉, tl; dr은 다음과 같습니다. 원하는 것을 수행하려면 (한 함수 호출 내에서 필터링 및 매핑)Array.reduce()
.
그러나, 더 읽기 와 (덜 중요한)은 일반적으로 속도가 매우 빠르고 이 방법은 사용 필터이며 서로 연결하는지도 :
[1,2,3].filter(num => num > 2).map(num => num * 2)
다음은 Array.reduce()
작동 방식과이를 사용하여 한 번의 반복으로 필터 및 매핑을 수행하는 방법에 대한 설명입니다 . 다시 말하지만, 이것이 너무 요약되어 있다면 위에 링크 된 블로그 게시물을 보는 것이 좋습니다. 이는 명확한 예와 진행 과정이 포함 된 훨씬 더 친숙한 소개입니다.
(일반적으로 익명) 함수 인 인수를 줄입니다.
이 익명 함수 는 두 개의 매개 변수를 사용합니다. 하나 (map / filter / forEach에 전달 된 익명 함수)는 작동 할 반복자입니다. 그러나이를 줄이기 위해 전달 된 익명 함수에 대한 또 다른 인수가 있는데, 이러한 함수는 허용하지 않으며 , 이는 종종 memo 라고하는 함수 호출 사이에 전달 될 값입니다 .
Array.filter ()는 하나의 인수 (함수) 만 사용하지만 Array.reduce ()는 중요한 (선택 사항이지만) 두 번째 인수도 사용합니다. 즉, 해당 익명 함수에 전달 될 '메모'의 초기 값은 첫 번째 인수이며 이후에 함수 호출 사이에 변형 및 전달 될 수 있습니다. (제공되지 않은 경우 첫 번째 익명 함수 호출의 'memo'는 기본적으로 첫 번째 iteratee가되고 'iteratee'인수는 실제로 배열의 두 번째 값이됩니다.)
우리의 경우에는 빈 배열을 전달하여 시작하고, 함수에 따라 반복자를 배열에 삽입할지 여부를 선택합니다. 이것이 필터링 프로세스입니다.
마지막으로 각 익명 함수 호출에 대해 '진행중인 배열'을 반환하고, reduce는 해당 반환 값을 가져와 다음 함수 호출에 인수 (메모라고 함)로 전달합니다.
이렇게하면 필터와 맵이 한 번의 반복에서 발생하여 필요한 반복 횟수를 절반으로 줄일 수 있습니다.하지만 반복 할 때마다 두 배의 작업 만 수행하므로 자바 스크립트에서 그렇게 비용이 많이 들지 않는 함수 호출 외에는 아무것도 저장되지 않습니다. .
더 자세한 설명은 MDN 문서 (또는이 답변의 시작 부분에 언급 된 내 게시물)를 참조하십시오.
Reduce 호출의 기본 예 :
let array = [1,2,3];
const initialMemo = [];
array = array.reduce((memo, iteratee) => {
if (iteratee > 1) {
memo.push(iteratee * 2);
}
return memo;
}, initialMemo)
console.log(array)
더 간결한 버전 :
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
첫 번째 iteratee는 1보다 크지 않으므로 필터링되었습니다. 또한 그 존재를 명확하게하고주의를 끌기 위해 이름이 지정된 initialMemo에 유의하십시오. 다시 한 번, 첫 번째 익명 함수 호출에 'memo'로 전달되고 익명 함수의 반환 된 값은 다음 함수에 'memo'인수로 전달됩니다.
메모에 대한 고전적인 사용 사례의 또 다른 예는 배열에서 가장 작거나 가장 큰 숫자를 반환하는 것입니다. 예:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
자신의 감소 함수를 작성하는 방법의 예 (이는 종종 다음과 같은 함수를 이해하는 데 도움이 됨) :
test_arr = [];
test_arr.my_reducer = function(reduceFunc, initialMemo) {
const initialMemoIsIndexZero = arguments.length < 2;
let memo = initialMemoIsIndexZero ? this[0] : initialMemo;
const initialIteratee = initialMemoIsIndexZero ? 1 : 0;
for (var i = initialIteratee; i < this.length; i++) {
memo = reduceFunc(memo, this[i]);
}
return memo;
}
예를 들어 실제 구현에서는 인덱스와 같은 항목에 액세스 할 수 있지만 이것이 요점에 대한 복잡하지 않은 느낌을 얻는 데 도움이되기를 바랍니다.