Array.prototype.reduce라는 짐승

reduce() JavaScript의 기능적 스타일 프로그래밍과 관련하여 메소드의 절대 짐승입니다. 더 많이 사용할수록 여기저기서 터지는 사용 사례를 더 많이 볼 수 있습니다.

나는 최근에 배열을 다루어야 할 때마다 그것이 나의 goto 메소드가되었다는 것을 깨달았습니다. 그래서 내 코드를 살펴보고 많은 예제를 찾았습니다. 그 중 일부는 이 게시물에 나열할 것입니다. 그러나 그 전에 방법 자체에 대한 간단한 검토부터 시작하겠습니다.

서명




arr.reduce((acc, current, index, array) => {
  // work goes here
}, initial);

reduce()는 두 개의 매개변수를 사용합니다.
  • callback 함수가 첫 번째입니다. reduce() 배열의 모든 요소를 ​​살펴보고 다음 값을 전달합니다callback.
  • acc 또는 누산기에서 이 값은 결과를 추적하기 위해 모든 호출에서 업데이트되는 상태와 같습니다
  • .
  • 첫 번째 호출의 경우 두 번째 매개변수로 제공되는 initial 값과 같습니다.
  • 그리고 후속 호출에서 acc는 이전 callback 호출에서 반환된 값이 됩니다.
  • current , 우리가 다루고 있는 배열의 요소.
  • index , 배열의 현재 인덱스
  • array , 어레이 자체

  • 두 번째 매개변수는 initial 이고 첫 번째 값은 acc 입니다. 이것은 선택 사항이며 제공되지 않는 경우 acc가 배열의 첫 번째 요소가 됩니다.

  • 간단한 예


    reduce()의 매우 일반적인 예는 정수 배열의 합을 계산하는 것입니다.

    [1, 2, 3, 4, 5].reduce((sum, integer) => sum + integer, 0);
    


    이 예에서는 indexarray 가 필요하지 않습니다. 이는 일반적으로 reduce() 의 경우입니다. 그리고 sum, integer, 0는 각각 acc, current, initial의 역할을 한다.

    이제 몇 가지 실용적인 예



    위에서 reduce() 의 예를 찾기 위해 일부 코드를 살펴봤다고 언급했습니다. 나는 그 중 일부를 아래에 나열했는데, 이는 새로운 사용 사례를 나타낼 만큼 충분히 다릅니다.

    I have trimmed the project specific code from these examples to keep the short



    1. 부울로 줄이기



    파일 경로( id )가 있고 경로가 watching 배열의 디렉토리 또는 파일에 속하는지 알고 싶습니다.

    return watching.reduce((acc, curr) => {
      return acc || id.startsWith(path.join(__dirname, curr));
    }, false);
    


    2. 객체의 특정 속성/키를 사용하여 객체 배열을 맵으로 변환



    데이터베이스에서 받은 개체 배열이 있습니다. 하지만 나중에 처리할 수 있도록 간단한 지도로 변환하고 싶습니다. 이러한 모든 객체는 공통 구조와 고유 식별자(기본 키)를 저장하는 키를 가지고 있습니다.

    데이터의 예,

    // docs array
    const docs = [{
      id: 'id-1',
      name: 'K Dilkington',
      style: 'orange',
    }, {
      id: 'id-2',
      name: 'Lanky Fellow',
      style: 'googly',
    }];
    
    // result
    const result = {
      'id-1': {
        id: 'id-1',
        name: 'K Dilkington',
        style: 'orange',
      },
      'id-2': {
        id: 'id-2',
        name: 'Lanky Fellow',
        style: 'googly',
      },
    };
    



    function makeMap(docs, key) {
      return docs.reduce((map, doc) => {
        map[doc[key]] = doc;
        return map;
      }, {});
    }
    


    이제 makeMap(docs, 'id') 를 사용하여 이 함수를 호출하여 원하는 지도를 만들 수 있습니다.

    3. 배열의 배열을 평평하게 하기



    아주 흔한 경우입니다. 배열의 배열이 있고 그것들을 단일 배열로 결합하고 싶습니다.

    function flatten(arr) {
      return arr.reduce((acc, current) => {
        return acc.concat(current);
      }, []);
    }
    
    
    flatten([['1', '2'], ['3', 4], [{}, []]]) // => [ '1', '2', '3', 4, {}, [] ]
    


    4. filter() 작업하기 - 상당히 불필요합니다 :)



    플레이어 배열에서 유효한 ID를 가진 플레이어를 필터링합니다(여기서 mongoId).

    game.players.reduce((acc, val) => {
      if (is.existy(val.mongoId)) {
        acc.push(val.mongoId);
      }
      return acc;
    }, []);
    


    5. 깊은 Object.assign


    Object.assign 소스 객체에서 주어진 객체로 값을 복사하지만 얕은 복사를 수행하고 주어진 객체도 변경합니다.

    깊은 복사를 수행하고 주어진 객체를 변경하지 않는 함수( deepAssign )를 원합니다.

    const source = {
      l1: {
        inside: true,
        prop: 'in',
      },
      prop: 'value',
    };
    const target = {
      prop: 'out',
      l1: {
        prop: 'inisde',
      },
    }
    
    const shallow = Object.assign(source, target);
    /*
    shallow = {
      "l1": {
        "prop": "inisde"
      },
      "prop": "out"
    }
    */
    
    const deep = deepAssign(source, target);
    /*
    deep = {
      "l1": {
        "inside":true,
        "prop": "inisde"
      },
      "prop": "out"
    }
    



    function deepAssign(object, update, level = 0) {
      if (level > 5) {
        throw new Error('Deep Assign going beyound five levels');
      }
    
      return Object.keys(update).reduce((acc, key) => {
        const updatewith = update[key];
        if (is.not.existy(updatewith)) {
          return acc;
        }
    
        // lets just suppose `is` exists
        if (is.object(updatewith) && is.not.array(updatewith)) {
          acc[key] = deepAssign(object[key], updatewith, level + 1);
          return acc;
        }
    
        acc[key] = updatewith;
        return acc;
      }, Object.assign({}, object));
    }
    


    우리는 여기서 재귀를 사용하고 있으며 stack 를 죽이고 싶지 않습니다. 따라서 우리가 신경써야 하는 소스 객체 내부의 얼마나 많은 레벨을 확인하는 간단한 검사입니다.

    6. 약속 연결



    직렬로 실행해야 하는 4개의 비동기 함수가 있으며 이전 함수의 결과를 다음 함수에 제공합니다.

    const arr = [fetchData, updateData, postData, showData];
    const response = arr.reduce((acc, current) => {
      // (cue alarm sirens) no error handling
      return acc.then(current));
    }, Promise.resolve(userId));
    
    response.then(data => {
      // data is final response
    });
    


    그게 다야.



    나는 몇 가지 더 많은 예를 찾았지만, 그들은 그들 자신의 비틀림으로 거의 동일한 스토리라인을 따르고 있었습니다.

    마지막으로, 읽어주셔서 감사합니다. reduce()의 마법 같은 사용 사례가 있거나 이 게시물에서 실수가 있으면 알고 싶습니다.

    좋은 웹페이지 즐겨찾기