JS進級編--JS配列reduce()方法詳細と高級技巧

4674 ワード

基本概念
reduce()メソッドはアキュムレータとして関数を受信し、配列内の各値(左から右へ)は縮小され、最終的には1つの値になります.
reduceは、配列中の各要素に対して順にコールバック関数を実行し、配列中の削除または未割り当ての要素を含まず、4つのパラメータを受け入れます.初期値(または前回のコールバック関数の戻り値)、現在の要素値、現在のインデックス、reduceの配列を呼び出します.
構文:
arr.reduce(callback,[initialValue])
  • calback(実行配列内の各値の関数は、4つのパラメータを含む)
  • previous Value(前回のコールバックの値、または提供された初期値)
  • currentValue
  • index(現在の要素の配列内のインデックス)
  • array(reduceを呼び出す配列)
  • initial Value(初めてコールされたcalbackの最初のパラメータとして.)
  • 簡単なアプリケーション
    例1:
    var items = [10, 120, 1000];
    
    // our reducer function
    var reducer = function add(sumSoFar, item) { return sumSoFar + item; };
    
    // do the job
    var total = items.reduce(reducer, 0);
    
    console.log(total); // 1130
    
    reduce関数は初期値0に基づいて連続的に重畳し,最も簡単な総和の実現を達成することが分かった.
    reduce関数の戻り結果のタイプは、着信の初期値と同じであり、前の例では初期値はnumberタイプであり、同じ原理で、初期値はobjectタイプであってもよい.
    例2:
    var items = [10, 120, 1000];
    
    // our reducer function
    var reducer = function add(sumSoFar, item) {
      sumSoFar.sum = sumSoFar.sum + item;
      return sumSoFar;
    };
    
    // do the job
    var total = items.reduce(reducer, {sum: 0});
    
    console.log(total); // {sum:1130}
    
    アプリケーション
    reduce法を用いてマルチ次元のデータ重ね合わせを行うことができる.上記の例の初期値{sum:0}のように、これは1次元の動作だけであり、複数の属性の重ね合わせに関連する場合、{sum:0、total InEuros:0、totalInYen:0}には、対応する論理が必要である.
    次の方法では,分割した方法を用いて,reduce関数の最初のパラメータcalbackを配列としてカプセル化し,配列の各関数によって単独に重畳し,reduce動作を完了する.すべてのすべては一つのmanager関数を通じて流れを管理し、初期パラメータを伝達する.
    var manageReducers = function(reducers) {
      return function(state, item) {
        return Object.keys(reducers).reduce(
          function(nextState, key) {
            reducers[key](state, item);
            return state;
          },
          {}
        );
      }
    };
    
    上にはmanager関数の実装があり、reducersオブジェクトをパラメータとして返し、reduceの最初のパラメータとして、calbackタイプの関数を返します.この関数の内部では、多次元の重畳作業(Object.keys()が実行される.
    このような分割の思想により、対象となる複数の属性を同時に重ね合わせることができます.完全なコードは以下の通りです.
    var reducers = {  
      totalInEuros : function(state, item) {
        return state.euros += item.price * 0.897424392;
      },
      totalInYen : function(state, item) {
        return state.yens += item.price * 113.852;
      }
    };
    
    var manageReducers = function(reducers) {
      return function(state, item) {
        return Object.keys(reducers).reduce(
          function(nextState, key) {
            reducers[key](state, item);
            return state;
          },
          {}
        );
      }
    };
    
    var bigTotalPriceReducer = manageReducers(reducers);
    var initialState = {euros:0, yens: 0};
    var items = [{price: 10}, {price: 120}, {price: 1000}];
    var totals = items.reduce(bigTotalPriceReducer, initialState);
    console.log(totals);
    ある学生の期末成績は次の通りです.
    var result = [
        {
            subject: 'math',
            score: 88
        },
        {
            subject: 'chinese',
            score: 95
        },
        {
            subject: 'english',
            score: 80
        }
    ];
    
    どうやってクラスメートの総成績を求めますか?
    var sum = result.reduce(function(prev, cur) {
        return cur.score + prev;
    }, 0);
    
    もし同級生が違反のため総成績で10点減点されたとします.初期値を-10に設定すればいいです.
    var sum = result.reduce(function(prev, cur) {
        return cur.score + prev;
    }, -10);
    
    この例に少し難度を加えます.もしこの学生の総成績の中で、各課の占める比重が違っていたら、それぞれ50%、30%、20%となりますが、どうやって最終的な重み付けの結果を求めるべきですか?
    解決策は以下の通りです.
    var dis = {
        math: 0.5,
        chinese: 0.3,
        english: 0.2
    }
    
    var sum = result.reduce(function(prev, cur) {
        return cur.score + prev;
    }, -10);
    
    var qsum = result.reduce(function(prev, cur) {
        return cur.score * dis[cur.subject] + pre;
    }, 0)
    
    console.log(sum, qsum);
    
    もう一つの例を見たら、どうやって文字列の中でアルファベットの出現回数を知ることができますか?
    var arrString = 'abcdaabc';
    
    arrString.split('').reduce(function(res, cur) {
        res[cur] ? res[cur] ++ : res[cur] = 1
        return res;
    }, {})
    
    このときreduceは、第2のパラメータによって、重畳結果の種類の初期値を設定することができるので、加算だけではなく、行列を一定の規則に従ってオブジェクトに変換したり、ある形式の配列を別の形式の配列に変換したりすることができます.みんなで試してもいいです.
    [1, 2].reduce(function(res, cur) { 
        res.push(cur + 1); 
        return res; 
    }, [])
    
    koaのソースコードの中に、Onlyモジュールがあります.モジュール全体は簡単にreduce方法の操作の対象に戻ります.
    var only = function(obj, keys){
      obj = obj || {};
      if ('string' == typeof keys) keys = keys.split(/ +/);
      return keys.reduce(function(ret, key){
        if (null == obj[key]) return ret;
        ret[key] = obj[key];
        return ret;
      }, {});
    };
    reduce概念を理解することによって、このモジュールは主にObjオブジェクトの中に存在するkeysのobjectオブジェクトを新規に作成して返したいです.
    var a = {
        env : 'development',
        proxy : false,
        subdomainOffset : 2
    }
    only(a,['env','proxy'])   // {env:'development',proxy : false}
    参照
    JSの内建関数reduce配列reduce方法の高級な技巧