ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL-2024.02.15 - JS - 고차함수와 Reduce
    > 기초/Javascript 2024. 2. 15. 21:50

     

    ------- 고차함수 란? 

     

    고차함수: 

    • JS에서 함수는 일급 객체이므로 함수를 값처럼 인수로 전달할수 있고, 반환  가능. 
    • 고차 함수는 외부 상태의 변경이나 가변 데이터를 피하고 immutability (불변성)을 지향하는 함수형 프로그래밍에 기반을 둠

     

    -------  Reduce 란? 

     

    Reduce 특징:

    • 고차함수: 함수를 인수로 전달받거나 함수를 반환하는 함수
    • 순수함수: 동일한 인자가 들어오면 항상 같은 값이 나와야하고 return 값으로만 소통하고 데이터베이스 호출이나 HTTP 호출 등 외부의 데이터 구조를 변형하는 호출을 허용하지 않는 함수

    설명:

    1. 자신을 호출한 배열의 모든 요소를 순회하며, 인수로 전달받은 콜백 함수를 반복 호출. 
    2. 콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫번째 인수로 전달하면서 콜백 함수를 호출하여 하나의 결과값을 만들어 반환.
    3. 원본 배열은 변경하지 않음
    4. 첫번째 인수로 콜백함수, 두번째 인수로 초기값 전달 받음.
    5. 첫번째 인수인 콜백함수는 4개의 인수 (초기값/콜백함수의 이전 반환값, reduce를 호추한 배열의 요소값-index, 배열 자체)가 전달

     

    예제: 

    const sum = [1,2,3,4].reduce((accumulator,currentVal,index,array) => accumulator + currentVal, 0);
    
    console.log(sum) // 10 >> 이러한 과정을 반복하여 reduce 메서드는 하나의 결과값 반환

     

     

    예제 설명:

    구분 콜백 함수에 전달되는 인수 콜백 함수의 반환값
    accumulator currentVal index array
    첫 번째 순회 0 (초기값) 1 0 [1,2,3,4] 1(accumulator +
    currentVal)
    두 번째 순회 1 2 1 [1,2,3,4] 3(accumulator +
    currentVal)
    세 번째 순회 3 3 2 [1,2,3,4] 6(accumulator +
    currentVal)
    네 번쨰 순회  6 4 3 [1,2,3,4] 10(accumulator +
    currentVal)

     

     

     

    사용 예제:

    // 1. 평균 구하기
    const average = [1,2,3,4,5,6].reduce((acc, cur, index , {length}) => {
    	return index === length - 1 ? (acc + cur) / length : acc + cur; 
    }, 0);
    console.log(average) // 3.5
    
    
    // 2. 최대값 구하기
    const max = [1,2,3,4,5].reduce((acc, cur) => acc > cur ? acc: cur, 0 )
    console.log(max) // 5
    
    
    // 3. 요소의 중복 횟수 구하기
    const countFruits = ['banana', 'apple', 'orange', 'orange', 'apple'].reduce((acc, cur) => {
    	// 1. 첫번째 순회 시, acc는 초기값인 {} 이고, cur은 첫번째 요소인 'banana'
        // 2. 초기값으로 전달받은 빈 객체에 요소값인 cur을 프로퍼티 키로, 요소의 갯수를 프로퍼티 값으로 할당
        // 3. 만약 프로퍼티 값이 undefined이면 프로퍼티 값을 1로 초기화한다. 
    	acc[cur] = (acc[cur] || 0 ) + 1
        return acc
    }, {}}
    
    // 4. 중첩 배열 평탄화 (.flat)
    const flatten = [1,[2,3],[4,5]].reduce((acc,val) => acc.concat(val),[]);
    console.log(flatten) // [1,2,3,4,5]
    
    
    // 5. 중복 요소 제거
    const duplicated = [ 1,2,1,3,5,4,5,3,4,4].reduce((acc,val,i , array) => 
    	array.indexOf(val) === i ?[...acc, val] : acc, [])
        // 1. i가 val의 인덱스와 같으면, 처음 순회하는 요소. 
        // 2. i가 val의 인덱스와 다르면, val은 중복된 요소

     

     

    이와 같이, 다양하게 reduce를 활용할 수 있다. Reduce 에서 초기값 (두번째로 인수) 생략 가능하지만,  언제나 초기값을 전달하는 것이 안전하다. 

     

     

    왜?

    const price = [
     {id: 1 , price: 100},
     {id: 2 , price: 200},
     {id: 3 , price: 300}
    ];
    
    > 초기값 X
    // 1. 첫번째 순회시, acc = {id: 1 , price: 100}, cur = {id: 2 , price: 200}
    // 2. 두번째 순회시, acc = 300, cur = {id: 3 , price: 300}
    // 2. 두번째 순횐시, acc 함수에 객체가 아닌 숫자 전달, thus undefined.
    
    return price.reduce((acc, cur) => acc.price + cur.price);
    
    
    > 초기값 O
    // 1. 첫번째 순회시, acc =   0, cur = {id: 1 , price: 100}
    // 2. 두번째 순회시, acc = 100, cur = {id: 2 , price: 200}
    // 2. 세번째 순회시, acc = 300, cur = {id: 3 , price: 300}
    
    return price.reduce((acc, cur) => acc.price + cur.price , 0);

     

     

     

     

     

    댓글

Designed by Tistory.