Lodash用來操作對象和集合,比Underscore擁有更多的功能和更好的性能。
官網:https://lodash.com/
引用:<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
安裝:npm install lodash
首先通過npm安裝lodash:
npm i --save lodash
在js文件中引用lodash:
var _ = require('lodash');
本系列包括:
● lodash用法系列(1),數組集合操作
● lodash用法系列(2),處理對象
● lodash用法系列(3),使用函數
● lodash用法系列(4),使用Map/Reduce轉換
● lodash用法系列(5),鏈式
● lodash用法系列(6),函數種種
■ 對字符串數組鏈式
var result = _(['a','b','c']) .at([0,1]) .value(); //[ 'a', 'b' ] console.log(result);
■ 對對象鏈式
_({a: 'b', c: 'd'})
.contains('b');
■ 對字符串鏈式
_('abcd')
.contains('b');
■ 使用chain實現鏈式
_.chain([3,2,1])
.sort()
.first()
.isNumber()
.value();
■ 多個過濾的鏈式
var collection = [ { name: 'Ellen', age: 20, enabled: true }, { name: 'Heidi', age: 24, enabled: false }, { name: 'Roy', age: 21, enabled: true }, { name: 'Garry', age: 23, enabled: false } ]; _(collection) .filter('enabled') .filter(function(item) { return item.age >= 21; }) .value(); // → [ { name: "Roy", age: 21, enabled: true } ]
■ filter結合where的鏈式
var collection = [ { name: 'Janice', age: 38, gender: 'f' }, { name: 'Joey', age: 20, gender: 'm' }, { name: 'Lauren', gender: 'f' }, { name: 'Drew', gender: 'm' } ]; _(collection) .where({ gender: 'f' }) .filter(_.flow(_.property('age'), _.isFinite)) .value(); // → [ { name: "Janice", age: 38, gender: "f" } ]
■ sortBy結合dropWhile鏈式
var collection = [ { first: 'Dewey', last: 'Mills' }, { first: 'Charlene', last: 'Larson' }, { first: 'Myra', last: 'Gray' }, { first: 'Tasha', last: 'Malone' } ]; _(collection) .sortBy('first') .dropWhile(function(item) { return _.first(item.first) < 'F'; }) .value(); // → // [ // { first: "Myra", last: "Gray" }, // { first: "Tasha", last: "Malone" } // ]
■ trim字符串
var name = ' Donnie Woods ', emptyString = _.partial(_.isEqual, ' '); _(name) .toArray() .dropWhile(emptyString) .dropRightWhile(emptyString) .join(''); // → "Donnie Woods"
■ sortBy結合takeWhile鏈式,獲取滿足條件的對象集合元素
var collection = [ { name: 'Jeannie', grade: 'B+' }, { name: 'Jeffrey', grade: 'C' }, { name: 'Carrie', grade: 'A-' }, { name: 'James', grade: 'A' } ]; _(collection) .sortBy('grade') .takeWhile(function(item) { return _.first(item.grade) === 'A'; }) .value(); // → // [ // { name: "James", grade: "A" }, // { name: "Carrie", grade: "A-" } // ]
■ reject鏈式
var obj = { first:'a', last:'b', age:25, enabled:true }; var tempResult = _(obj) .reject(_.isBoolean) .reject(_.isString) .value(); //[ 25 ] console.log(tempResult);
reject還可以接受回調函數。
function User(name, disabled){ this.name = name; this.disabled = disabled; } User.prototype.enabled = function(){ return !this.disabled; } var collection = [ new User('Phil', true), new User('Wilson', false), new User('Kathey', true), new User('Nina', false) ], //作為下面reject的回調函數 enabled = _.flow(_.identity, _.partialRight(_.result, 'enabled'));//由於是作為reject的回調函數,這里的enabled是User的原型方法enabled var result = _(collection) .reject('disabled') .value(); //[ User { name: 'Wilson', disabled: false }, // User { name: 'Nina', disabled: false } ] console.log(result); var result2 =_(collection) .reject(_.negate(enabled)) .value(); //[ User { name: 'Wilson', disabled: false }, // User { name: 'Nina', disabled: false } ] console.log(result2);
■ 關於negate方法
function isEven(num) { return num % 2 == 0; } var result = _.filter([1, 2, 3, 4, 5, 6], isEven); var negateResult = _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); //[ 2, 4, 6 ] console.log(result); [ 1, 3, 5 ] console.log(negateResult);
■ initial只接受除了集合中最后一個元素之外的所有元素
對於一個字符串,先用分步來做:
var string = 'abc\n'; var result1 = _(string) .slice() .value(); //[ 'a', 'b', 'c', '\n' ] console.log(result1); var result2 = _(result1) .initial() .value(); //[ 'a', 'b', 'c' ] console.log(result2) var result3=_(result2) .join(''); //abc console.log(result3);
然后用鏈式可以這樣做:
var oneResult = _(string) .slice() .initial() .join(''); //abc console.log(oneResult);
■ rest只接受除了集合中第一個元素之外的所有元素
var collection = [ { name: 'init', task: _.noop }, { name: 'sort', task: _.random }, { name: 'search', task: _.random } ]; var result = _(collection) .rest() .invoke('task') .value(); //[ 1, 0 ] 有時候是 [ 0, 0 ],不一定 console.log(result);
■ 判斷字符串是否含有某些字符串
var string = 'abc123'; var result =_(string) .filter(_.isString) .contains('c'); console.log(result);//true
■ 判斷數組中是否包含某個元素
var array = [ 'a', 'b', 'c', 1, 2, 3 ]; var result = _(array) .filter(_.isString) .contains('c'); console.log(result);//true
■ 所有集合元素都符合某種條件
var collection = [ 1414728000000, 1383192000000, 1351656000000, 1320033600000 ]; _(collection) .map(function(item) { return new Date(item); }) .every(function(item) { return item.getMonth() === 9 && item.getDate() === 31; }); // → true
■ 只要集合元素某些符合某種條件
var collection = [ { name: 'Danielle', age: 34, skill: 'Backbone' }, { name: 'Sammy', age: 19, skill: 'Ember' }, { name: 'Donna', age: 41, skill: 'Angular' }, { name: 'George', age: 17, skill: 'Marionette' } ]; var result=_(collection) .reject({ skill: 'Ember' }) .reject({ skill: 'Angular' }) .some(function(item) { return item.age >= 25; }); console.log(result);//true
■ size運用到對象上數的是鍵值對的數量
var object = { first: 'Charlotte', last: 'Hall' }; var result1 = _(object) .size(); console.log(result1);//2 var result2 = _(object) .omit('first') .size(); console.log(result2);//1
■ size運用到數組上數的是元素的數量
var array = _.range(10); var result =_(array) .drop(5) .size(); console.log(result);//5
■ countBy對對象某個字段的值進行分組並計數
如果分步走,就是:
var collection = [ { name: 'Pamela', gender: 'f' }, { name: 'Vanessa', gender: 'f' }, { name: 'Gina', gender: 'f' }, { name: 'Dennis', gender: 'm' } ]; //countBy對對象某個字段的值進行分組並計數 var r1 =_(collection) .countBy('gender') .value(); console.log(r1);//{ f: 3, m: 1 } //paris把對象的每一個鍵值作為數組元素,再把這個數組放到更大的數組 var r2=_(r1) .pairs() .value(); console.log(r2);//[ [ 'f', 3 ], [ 'm', 1 ] ] //排序 var r3=_(r2) .sortBy(1) .value(); console.log(r3);//[ [ 'm', 1 ], [ 'f', 3 ] ] //反轉 var r4=_(r3) .reverse() .value(); console.log(r4);//[ [ 'f', 3 ], [ 'm', 1 ] ] //pluck獲取想要的集合元素 var r5=_(r4) .pluck(0) .value(); console.log(r5);//[ 'f', 'm' ]
如果是鏈式,就是:
_(collection) .countBy('gender') .pairs() .sortBy(1) .reverse() .pluck(0) .value();
■ 對象的集合,對象元素中有數組字段,根據數組元素的某些條件自定義求和算法
var collection = [ { name: 'Chad', skills: [ 'backbone', 'lodash' ] }, { name: 'Simon', skills: [ 'html', 'css', 'less' ] }, { name: 'Katie', skills: [ 'grunt', 'underscore' ] }, { name: 'Jennifer', skills: [ 'css', 'grunt', 'less' ] } ]; var result = _(collection) .pluck('skills') .reduce(function(result, item){ return _.size(item) > 2 && _.contains(item, 'grunt') && result + 1; },0); console.log(result);//1
以上,通過pluck對象元素只留下了skills,是一個數組類型。通過reduce方法在滿足多個條件下求和。size統計對象字段數組的元素個數,contains判斷對象字段數組中是否包含某個元素。
■ 對象數組,為對象元素加上新的字段並分組
var collection = [ { name: 'Rudolph', age: 24 }, { name: 'Charles', age: 43 }, { name: 'Rodney', age: 37 }, { name: 'Marie', age: 28 } ]; var result = _(collection) .map(function(item){ var experience='seasoned veteran'; if(item.age<30){ experience='noob'; } else if(item.age<40){ experience='geek cred'; } return _.extend({experience: experience},item); }) .groupBy('experience') .map(function(item,key){ return key + ' ('+ _.pluck(item,'name').join(', ')+')'; }) .value(); //[ 'noob (Rudolph, Marie)', // 'seasoned veteran (Charles)', // 'geek cred (Rodney)' ] console.log(result);
■ 兩個數組的並集
var collection=_.sample(_.range(1,101),10); var result=_(collection) .union([25,50]) .sortBy() .value(); //[ 5, 18, 25, 40, 50, 62, 64, 72, 77, 78, 82, 87 ] console.log(result);
■ 對象集合,去掉對象元素字段重復值
function name(item){ return item.first + ' '+item.last; } var collection = [ { first: 'Renee', last: 'Morris' }, { first: 'Casey', last: 'Wise' }, { first: 'Virginia', last: 'Grant' }, { first: 'Toni', last: 'Morris' } ]; var result1 = _(collection) .uniq('last') //去掉last字段重復的值 .sortBy('last') .value(); console.log(result1);
■ 對象數組,where結合pluck鏈式
var collection = [ { gender: 'f', dob: new Date(1984, 3, 8) }, { gender: 'm', dob: new Date(1983, 7, 16) }, { gender: 'f', dob: new Date(1987, 2, 4) }, { gender: 'm', dob: new Date(1988, 5, 2) } ]; var result =_(collection) .where({gender: 'm'}) .pluck('dob') .map(function(item){ return item.toLocaleString(); }) .value(); //[ '1983-08-16 00:00:00', '1988-06-02 01:00:00' ] console.log(result);
■ without排除數組元素
var collection= _.range(1,11); var result = _(collection) .without(5, _.first(collection), _.last(collection)) .reverse() .value(); //[ 9, 8, 7, 6, 4, 3, 2 ] console.log(result);
■ 對象數組,找出某個字段滿足最小值的對象元素
var collection = [ { name: 'Daisy', wins: 10 }, { name: 'Norman', wins: 12 }, { name: 'Kim', wins: 8 }, { name: 'Colin', wins: 4 } ]; var result=_(collection) .reject(function(item){ return item.wins<5; }) .min('wins'); //{ name: 'Kim', wins: 8 } console.log(result);
■ 對象數組,計算對象元素的字段的最大值,找出其所對應的對象元素
var collection = [ { name: 'Kerry', balance: 500, credit: 344 }, { name: 'Franklin', balance: 0, credit: 554 }, { name: 'Lillie', balance: 1098, credit: 50 }, { name: 'Clyde', balance: 473, credit: -900 } ]; var result=_(collection) .filter('balance') .filter('credit') .max(function(item){ return item.balance +item.credit; }) //{ name: 'Lillie', balance: 1098, credit: 50 } console.log(result);
■ 對象集合,找出附后某個字段值條件的對象元素在數組中的位置
function rank(coll, name){ return _(coll) .sortBy('score') .reverse() .pluck('name') .indexOf(name) + 1; } var collection = [ { name: 'Ruby', score: 43 }, { name: 'Robert', score: 59 }, { name: 'Lindsey', score: 38 }, { name: 'Marty', score: 55 } ]; var result = rank(collection, 'Ruby'); console.log(result);//3
■ 獲取兩個數組的差集
var collection = _.range(1, 51),//1-50的數 odds = _.filter(_.range(1, 101), function(item) { return item % 2; });//1-100的偶數 _(collection) .difference(odds) .takeRight(10) .reverse() .value();
分開寫就是:
var collection = _.range(1, 51),//1-50的數 odds = _.filter(_.range(1, 101), function(item) { return item % 2; });//1-100的偶數 var result1=_(collection) .difference(odds)//兩個集合的差集 .value(); //[ 2,4,6,8,10,12,14,16,18,20,22,24,26,28, 30,32,34,36,38,40,42,44,46,48,50 ] console.log(result1); var result2=_(result1) .takeRight(10) .value(); //[ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50 ] console.log(result2); var result3 = _(result2) .reverse() .value(); //[ 50, 48, 46, 44, 42, 40, 38, 36, 34, 32 ] console.log(result3);
■ 獲取兩個數組的異或
var collection = _.range(1, 26), evens = _.reject(_.range(1, 51), function(item) { return item % 2; }); _(collection) .xor(evens) .reverse() .value();
■ 在鏈式中加入自己的回調函數,排除對象數組某個字段的最大和最小值
var collection = [ { name: 'Stuart', age: 41 }, { name: 'Leah', age: 26 }, { name: 'Priscilla', age: 37 }, { name: 'Perry', age: 31 } ], min, max; var result = _(collection) .filter(function(item){ return item.age >=30; }) .tap(function(coll){ min= _.min(coll,'age'), max= _.max(coll,'age') }) .reject(function(item){ return item.age === max.age; }) .value(); //[ { name: 'Priscilla', age: 37 }, { name: 'Perry', age: 31 } ] console.log(result);
■ 在鏈式中注入值
var collection = _.range(1, _.random(11)), result; result=_(collection) .thru(function(coll){ return _.size(coll)>5?coll:[]; }) .reverse() .value(); var finalResult = _.isEmpty(result) ? 'No Results' : result.join(','); //有時 6,5,4,3,2,1 //有時 No Results console.log(finalResult);
■ 過濾對象的鍵
var object = { firstName: 'Jerald', lastName: 'Wolfe', age: 49 }; var result =_(object) .keys() //獲取所有的鍵 .filter(function(item){ return (/name$/i).test(item);//不以name結尾的 }) .thru(function(items){//items表示過濾下來的鍵的集合 return _.at(object, items);//從object中找出與這些鍵對相的鍵值 }) .value(); //[ 'Jerald', 'Wolfe' ] console.log(result);
■ 過濾對象的值
var object = { first: 'Connie', last: 'Vargas', dob: new Date(1984, 08, 11) }; _(object) .values() .filter(_.isDate) .map(function(item) { return item.toLocaleString(); }) .value(); // → [ "9/11/1984, 12:00:00 AM" ]
■ 對象數組,忽略對象元素某個字段
var collection = [ { first: 'Tracey', last: 'Doyle', age: 40 }, { first: 'Toby', last: 'Wright', age: 49 }, { first: 'Leonard', last: 'Hunt', age: 32 }, { first: 'Brooke', last: 'Briggs', age: 32 } ]; _(collection) .indexBy('last') .pick(function(value) { return value.age >= 35; }) .transform(function(result, item, key) { result[key] = _.omit(item, 'last'); }) .value(); // → // { // Doyle: { first: "Tracey", age: 40 }, // Wright: { first: "Toby", age: 49 } // }
■ 用來包裹一些列鏈式動作的函數可以看做是wrapper
//coll集合 //prop排序的屬性 //count要獲取的數量 function best(coll, prop, count){ return _(coll) .sortBy(prop) .takeRight(count); } var collection = [ { name: 'Mathew', score: 92 }, { name: 'Michele', score: 89 }, { name: 'Joe', score: 74 }, { name: 'Laurie', score: 83 } ]; var bestScore = best(collection, 'score',2); //[ { name: 'Michele', score: 89 }, // { name: 'Mathew', score: 92 } ] console.log(bestScore.value()); best函數並沒有真正執行,可以看做是一個wrapper。
參考資料:lodash essentials
未完待續~~