lodash中国語学習拾零のMap/Reduce編

38675 ワード

作者:Soring_Tigerの転載は出所を明記してください.http://blog.csdn.net/Soaring_タイガー
前情摘要1:lodash中国語学習拾零のAray編前情摘要2:lodash中国語学習拾零のChin編前情提要3:lodash中国語学習拾零のCollection編前情提要4:lodash中国語学習拾零のObject編前情提要5:lodash中国語学習拾零のFunct篇
6、lodashでデータを行うMap/Reduce
私達はプログラミングする過程で、大量の出会う仕事はデータの転換で、前の何篇の文章はlodashのデータの変換の中の作用を言及して、本編はMap/Reduceをめぐって更に深い探求を行います.
6.1データを選ぶ.pluckまたは.map
前の方はもうたくさん見ました.pluckでデータを選ぶ例
var collection = [
       { name: 'Virginia', age: 45 },
       { name: 'Debra', age: 34 },
       { name: 'Jerry', age: 55 },
       { name: 'Earl', age: 29 }
];

_.pluck(collection, 'age');
   // → [ 45, 34, 55, 29 ]
実は私達もmapで同じことができます.
var collection = [
       { name: 'Michele', age: 58 },
       { name: 'Lynda', age: 23 },
       { name: 'William', age: 35 },
       { name: 'Thomas', age: 41 }
];

_.map(collection, 'name');
   // →
   // [
   // "Michele",
   // "Lynda",
   // "William",
   // "Thomas"
   // ]
結果は同じように見えますが、pluckは.mapに基づいてパッケージ化されています.また、pluckは文字列(String)のみを選択のパラメータとしています.mapの機能はより強力です.
6.2マッピングセットMapping collection
6.2.1用.mapとシールドのプロパティ
別名:_.collect
map(collection、iteratee=u.identity)、[thisArg]の最初のパラメータは処理する配列であり、2番目のパラメータはディズマリーであり、このディケンサは関数でもいいし、対象でもいいし、文字列でもいい.
var collection = [
       { first: ' ', last: '  ', age: 23 },
       { first: ' ', last: ' ', age: 31 },
       { first: ' ', last: ' ', age: 44 },
       { first: ' ', last: ' ', age: 38 }
];

//       
_.map(collection, function(item) {
       return _.pick(item, [ 'first', 'last' ]);
}); 

   // → 
   // [
   //   { first: ' ', last: '  '},
   //   { first: ' ', last: ' '},
   //   { first: ' ', last: ' ' },
   //   { first: ' ', last: ' ' }
   // ]

//       
_.map(collection,{first: ' '});

//[true,false,false,false]

// omit       
_.map(collection, function(item) {
       return _.omit(item, 'first');
});

//[
//  {"last":"  ","age":23},
//  {"last":" ","age":31},
//  {"last":" ","age":44},
//  {"last":" ","age":38}
//]

//          
function invalidAge(value, key) {
    return key === 'age' && value < 40;
}

_.map(collection, function(item) {
    return _.omit(item, invalidAge);
});

//[
//  {"first":" ","last":"  "},
//  {"first":" ","last":" "},
//  {"first":" ","last":" ","age":44},
//  {"first":" ","last":" "}
//]
6.2.2計算を実行する
var collection = [
       { name: 'Valerie', jqueryYears: 4, cssYears: 3 },
       { name: 'Alonzo', jqueryYears: 1, cssYears: 5 },
       { name: 'Claire', jqueryYears: 3, cssYears: 1 },
       { name: 'Duane', jqueryYears: 2, cssYears: 0 }
];

//     ,                     
   _.map(collection, function(item) {
       return _.extend({
           experience: item.jqueryYears + item.cssYears,
           specialty: item.jqueryYears >= item.cssYears ?
               'jQuery' : 'CSS'}, 
           item);
   });
   // → 
   // [ 
   // {
   // experience": 7,
   // specialty": "jQuery",
   // name": "Valerie",
   // jqueryYears": 4,
   // cssYears: 3
   // }, 
   // {
   // experience: 6,
   // specialty: "CSS",
   // name: "Alonzo",
   // jqueryYears: 1,
   // cssYears: 5
   // }, 
   // {
   // experience: 4,
   // specialty: "jQuery",
   // name: "Claire",
   // jqueryYears: 3,
   // cssYears: 1
   // }, 
   // {
   // experience: 2,
   // specialty: "jQuery",
   // name: "Duane",
   // jqueryYears: 2,
   // cssYears: 0
   // }
   // ]
6.2.3コール機能
ディケンサは直接既存のlodash関数を使うことができます.使用できるのは以下のようなものがあります.
ary,calback,chunk,clone,create,curry,curryRight,drop,drop,drop Right,every,fill,flatent,invert,max,min,parseInt,slece,sortBy,take,template,trim,trimft,trimft,trimft,trimft,tramrangeranger,tram,trantft,tram,stranger.
実際には、入力パラメータが一つしかない限り、入力パラメータの戻り値に基づいた新しい関数があります.
//            size
var collection = [
       [ 1, 2 ],
       [ 1, 2, 3 ],
       { first: 1, second: 2 },
       { first: 1, second: 2, third: 3 }
];

_.map(collection, _.size);
   // → [ 2, 3, 2, 3 ]
//          
//      compose         
//                   ,               
var collection = [
       [ 'Evan', 'Veronica', 'Dana' ],
       [ 'Lila', 'Ronald', 'Dwayne' ],
       [ 'Ivan', 'Alfred', 'Doug' ],
       [ 'Penny', 'Lynne', 'Andy' ]
];

_.map(collection, _.compose(_.first, function(item) {
       return _.sortBy(item);
   }));
   // → [ "Dana", "Dwayne", "Alfred", "Andy" ]
6.2.4フィルタリングとマッピング
var collection = [
       { name: 'Karl', enabled: true },
       { name: 'Sophie', enabled: true },
       { name: 'Jerald', enabled: false },
       { name: 'Angie', enabled: false }
   ];

// compose         ,     collection      
_.compose(
       _.partialRight(_.map, 'name'),
       _.partialRight(_.filter, 'enabled')
   )(collection);
// → [ "Karl", "Sophie" ]
6.3マッピングオブジェクト
lodashの世界では、対象も集合の一種と見なされていますが、特殊性もありますので、ここでは個別に対象のマッピングを検討しています.
6.3.1処理対象中のkey
var object = {
       first: 'Ronald',
       last: 'Walters',
       employer: 'Packt'
   };
   _.map(_.sortBy(_.keys(object)), function(item) {
       return object[item];
   });
   // → [ "Packt", "Ronald", "Walters" ]
var users = {},
       preferences = {};
   _.each(_.range(100), function() {
       var id = _.uniqueId('user-');
       users[id] = { type: 'user' };
       preferences[id] = { emailme: !!(_.random()) };
});
   _.map(users, function(value, key) {
       return _.extend({ id: key }, preferences[key]);
}); 

// → 
// [
// { id: "user-1", emailme: true },
// { id: "user-2", emailme: false },
// ...
// ]
6.3.2呼び出し関数
オブジェクトのkeyは、数字や文字列だけでなく、関数でもありますが、コンテキストが変わるにつれて、関数は常に正常に使用されているわけではありません.
var object = {
       first: 'Roxanne',
       last: 'Elliot',
       name: function() {
           return this.first + ' ' + this.last;
       },
       age: 38,
       retirement: 65,
       working: function() {
           return this.retirement - this.age;
       }
};
   _.map(object, function(value, key) {
       var item = {};
       item[key] = _.isFunction(value) ? object[key]() : value
    return item;
});
// → 
// [
// { first: "Roxanne" },
// { last: "Elliot" },
// { name: "Roxanne Elliot" },
// { age: 38 },
// { retirement: 65 },
// { working: 27 }
// ]

//  result()         ,      
_.map(object, function(value, key) {
    var item = {};
    item[key] = _.result(object, key);
    return item;
});

// → 
// [
// { first: "Roxanne" },
// { last: "Elliot" },
// { name: "Roxanne Elliot" },
// { age: 38 },
// { retirement: 65 },
// { working: 27 }
// ]
6.3.3マッピングkey-valueペア
function capitalize(s) {
       return s.charAt(0).toUpperCase() + s.slice(1);
}

function format(label, value) {
       return '<label>' + capitalize(label) + ':</label>' +
           '<strong>' + value + '</strong>';
}

var object = {
       first: 'Julian',
       last: 'Ramos',
       age: 43 
};

_.map(_.pairs(object), function(pair) {
       return format.apply(undefined, pair);
}); 

// → 
// [
// "<label>First:</label><strong>Julian</strong>",
// "<label>Last:</label><strong>Ramos</strong>",
// "<label>Age:</label><strong>43</strong>"
// ]
6.4簡略化集合
本節は_.reduceの使い方
reduce(collection、「iteratee=u.identity」、「accumullator」、「thisArg」)の最初のパラメータは処理すべきセットであり、配列、オブジェクト、文字列の2番目のパラメータは、サブジェネレータの3番目のパラメータは、アキュムレータの4番目のパラメータは、thisArgである.
_.reduce([1, 2], function(total, n) {
  return total + n;
});
// → 3

_.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
  result[key] = n * 3;
  return result;
}, {});
// → { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
6.4.1合計(Summing values)
var collection = [
       { ram: 1024, storage: 2048 },
       { ram: 2048, storage: 4096 },
       { ram: 1024, storage: 2048 },
       { ram: 2048, storage: 4096 }
];

_.reduce(collection, function(result, item) {
       return result + item.ram;
   }, 0);
// → 6144

_.reduce(collection, function(result, item) {
       return result + item.storage;
    }, 0);
// → 12288
6.4.2濾過と化簡(Filtering and reducing)
アキュムレータとは、初期値を提供する役割です.
var collection = [
       { name: 'Gina', age: 34, enabled: true },
       { name: 'Trevor', age: 45, enabled: false },
       { name: 'Judy', age: 71, enabled: true },
       { name: 'Preston', age: 19, enabled: false }
];

   _.reduce(_.filter(collection, 'enabled'), function(result, item) {
       result.names.push(item.name);
       result.years += item.age;
       return result;
   }, { names: [], years: 0 });

   // →
   // {
   // names: ["Gina","Judy" ],
   // years: 105
   // }
6.4.3最大値、最小値、平均値操作
//      
function score(item) {
       return _.reduce(item.scores, function(result, score) {
           return result + score;
       });
}

var collection = [
       { name: 'Madeline', scores: [ 88, 45, 83 ] },
       { name: 'Susan', scores: [ 79, 82, 78 ] },
       { name: 'Hugo', scores: [ 90, 84, 85 ] },
       { name: 'Thomas', scores: [ 74, 69, 78 ] }
];

_.min(collection, score);
// →
// {
// name: "Madeline",
// scores: [
// 88,
// 45,
// 83
// ]
// }

_.max(collection, score);

// →
// {
// name: "Hugo",
// scores: [
// 90,
// 84,
// 85
// ]
// }
//    
function average(items) {
       return _.reduce(items, function(result, item) {
           return result + item;
       }) / items.length;
}

var collection = [
       { name: 'Anthony', scores: [ 89, 59, 78 ] },
       { name: 'Wendy', scores: [ 84, 80, 81 ] },
       { name: 'Marie', scores: [ 58, 67, 63 ] },
       { name: 'Joshua', scores: [ 76, 68, 74 ] }
];

_.reduce(collection, function(result, item, index, coll) {
       var ave = average(item.scores);
       result.push(ave);
       if (index === (coll.length - 1)) {
           return average(result);
       }
       return result;
   }, []).toFixed(2);
   // → "73.08"
6.5簡素化の対象
6.5.1化Keys
var object = {
           first: 'Kerry',
           last: 'Singleton',
            age: 41 
      },

allowed = [ 'first', 'last' ];

_.reduce(object, function(result, value, key) {
       if (_.contains(allowed, key)) {
           result[key] = value;
       }
       return result;
   }, {});

// → { first: "Kerry", last: "Singleton" }

_.pick(object, allowed);
// → { first: "Kerry", last: "Singleton" }
6.5.2オブジェクトアキュムレータ
var object = {
       first: '&lt;strong&gt;Nicole&lt;/strong&gt;',
       last: '&lt;strong&gt;Russel&lt;/strong&gt;',
       age: 26
};

_.transform(object, function(result, value, key) {
       if (_.isString(value)) {
           result[key] = _.unescape(value);
       }
}); 
    // → 
   // {
   // first: "<strong>Nicole</strong>",
   // last: "<strong>Russel</strong>"
   // }
function Person(first, last) {
       this.first = first;
       this.last = last;
   }

Person.prototype.name = function name() {
       return this.first + ' ' + this.last;
};

var object = new Person('Alex', 'Rivera');
   _.transform(object, function(result, value, key) {
       if (_.isString(value)) {
           result[key] = value.toUpperCase();
       }
   }).name();
   // → "ALEX RIVERA"
6.5.3バインディングコンテキスト
var app = {
       states: [
           'running',
           'off',
           'paused'
       ],
       machines: [
           { id: _.uniqueId(), state: 1 },
           { id: _.uniqueId(), state: 0 },
           { id: _.uniqueId(), state: 0 },
           { id: _.uniqueId(), state: 2 }
        ] 
};

var mapStates = _.partialRight(_.map, function(item) {
       return _.extend({
           state: this.states[item.state]
       }, _.pick(item, 'id'));
}, app);

mapStates(app.machines);
   // →
   // [
   //   { state: "off", id: "1" },
   //   { state: "running", id: "2" },
   //   { state: "running", id: "3" },
   //   { state: "paused", id: "4" }
   // ]
6.6 Map/Reduceモード
6.6.1汎用コールバック関数
function add(item) {
       var result = _.clone(item);
       result[this.prop] += this.value;
       return result;
}

function upper(item) {
        var result = _.clone(item);
       result[this.prop] = result[this.prop].toUpperCase();
       return result;
}

var collection = [
       { name: 'Gerard', balance: 100 },
       { name: 'Jean', balance: 150 },
       { name: 'Suzanne', balance: 200 },
       { name: 'Darrell', balance: 250 }
];

var mapAdd = _.partial(_.map, collection, add),
       mapUpper = _.partial(_.map, collection, upper);

mapAdd({ prop: 'balance', value: 50 });
   // →
   // [
   // { name: "Gerard", balance: 150 },
   // { name: "Jean", balance: 200 },
   // { name: "Suzanne", balance: 250 },
   // { name: "Darrell", balance: 300 }
   // ]

mapAdd({ prop: 'balance', value: 100 });
   // →
   // [
   // { name: "Gerard", balance: 200 },
   // { name: "Jean", balance: 250 },
   // { name: "Suzanne", balance: 300 },
   // { name: "Darrell", balance: 350 }
   // ]

mapUpper({ prop: 'name'});
   // →
   // [
   // { name: "GERARD", balance: 100 },
   // { name: "JEAN", balance: 150 },
   // { name: "SUZANNE", balance: 200 },
   // { name: "DARRELL", balance: 250 }
   // ]
function sum(a, b) {
       return a + b[this.prop];
}

var collection = [
       { low: 40, high: 70 },
       { low: 43, high: 83 },
       { low: 39, high: 79 },
       { low: 45, high: 74 }
   ];

var reduceSum = _.partial(_.reduce, collection, sum, 0);

reduceSum({ prop: 'low' });
   // → 167

reduceSum({ prop: 'high' });
   // → 306
6.2 Map/Reduceチェーン
var collection = [
       { name: 'Wade', balance: 100 },
       { name: 'Donna', balance: 125 },
       { name: 'Glenn', balance: 90 },
       { name: 'Floyd', balance: 110 }
    ], 
    bonus = 25;

var mapped = _.map(collection, function(item) {
       return _.extend({
           bonus: item.balance + bonus
       }, item);
});

_.reduce(mapped, function(result, item, index, coll) {
       result += (item.bonus - item.balance) / item.bonus;
       if (index === (coll.length - 1)) {
           result = result / coll.length * 100;
       }
    return result;
}, 0).toFixed(2) + '%';
// → "19.23%"
lodash Map/Reduce小結:
この記事では、Map/Reduceにおけるlodashのアプリケーションを紹介します.Map部分では、どのようなKeyを選ぶか、どのように計算するかを考えて、Map操作を行い、操作対象を新しいオブジェクトや集合にマッピングします.Reduce部分では、どのようにデータを簡潔にするかを紹介します.