zoukankan      html  css  js  c++  java
  • lodash用法系列(5),链式

    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
    ';
    
    var result1 = _(string)
        .slice()
        .value();
    
    //[ 'a', 'b', 'c', '
    ' ]
    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

    未完待续~~

  • 相关阅读:
    在o(N log N)时间内使用恒定的空间复杂度对链表进行排序
    归并排序
    The method of type must override a superclass method解决方式
    android sdk design Iconography
    android sdk design Typography
    android sdk design Metrics and Grids
    android模拟器被点击时总是自动输入C的解决
    “System.Data.Entity.ModelConfiguration.ModelValidationException”类型的未经处理的异常在 EntityFramework.dll 中发生
    js中的this使用
    MVC身份认证 解决办法 测试可行
  • 原文地址:https://www.cnblogs.com/darrenji/p/5011488.html
Copyright © 2011-2022 走看看