lodash 中文学习拾零之 Collection篇
来源:互联网 发布:淘宝推广计划书 编辑:程序博客网 时间:2024/05/22 01:36
作者:Soaring_Tiger 转载请注明出处
前情提要1 : lodash中文学习拾零之Array篇
前情提要2:lodash 中文学习拾零之 Chain篇
3、Collection(集合)与Array(数组)的区别
对于lodash的初学者而言,可能一下子搞不清楚为什么lodash提供了Array和Collection两类方法?表面上看起来好像这两套方法有些地方是可以互换的,那么我们就进一步来澄清什么是Collection方法,什么是Array方法。
在lodash中,Collection是一个抽象的概念,指的是那些我们准备用来迭代的Javascript object,可以是 数组、字符串或者object对象,至于这些数据类型之间的差别细节,则被lodash隐藏起来了,作为开发者你不用操心。
而lodash的 Array方法则没有那么抽象,它们要求你处理的就是实实在在的数组。从这个意义上讲,即便Array方法没有显式的检查你提交的数据类型,但是它们要求你提交的数据得有数值型length属性(a numerical length property)。
实际上,在大部分时候,你并不需要严格得区分 arrays 和 collections 之间的差别,因为你面对的大多数collections都是以数组的形式出现的,只有在比较少的情况下,你会面临着差别 。所以你只要记住,Array方法是严格要求数据类型(有数值型length属性)的就行了。
3.1 遍历collection元素
3.1.1 .forEach
_.forEach是处理Collection最基础的函数了,下面这个例子非常简单,就是告诉你forEach是如何进行迭代(循环)的:
var collection = [ '红', '黄', '蓝', '绿']; _.forEach(collection, function(name) { console.log(name); }); // → // 红 // 黄 // 蓝 // 绿
_.forEach有三个参数,第一个参数是要处理的collection,第二个参数是迭代器(以匿名函数的形式出现),第三个参数是 The this binding of iteratee(可以理解为迭代器里的this绑定的方法).
_.forEach文档定义如下:
Aliases(别名):
_.eachArguments(参数):
1、collection (Array|Object|string): The collection to iterate over.
2、[iteratee=_.identity] (Function): The function invoked per iteration.
3、 [thisArg] (*): The this binding of iteratee.
//例子var collection = [100,200,300,400]; _.forEach(collection, function(value) { console.log(this.sqrt(value)); //对collection中的每个值开方 }, Math); //本例中thisArg绑定了Math的方法//10//14.142135623730951//17.320508075688775//20
当迭代发生的时候,每轮到一个元素都激活一次迭代器,迭代器有三个参数:
(1)被迭代的元素,(2)该元素的index或者key,(3)collection。
在迭代器返回false值时,允许整个迭代过程提早结束,如下面的例子:
var myCollection = [ '阿猫', '阿狗', '小黑', '阿花']; _.forEach(myCollection, function(name, index, collection) { if (name === '小黑') { console.log('小黑的index: ' + index); console.log(collection[index]); return false; } }); // → 小黑的index: 1 // → 小黑
3.1.2 .forEachRight
与_.forEach的执行方向相反,从最右侧的元素先开始进行迭代:
_([1, 2]).forEachRight(function(n) { console.log(n);}).value();// → 2// → 1
3.3 排序
排序是我们对collection进行操作时会经常遇到的问题,javascript自带的sort()、reverse()之类的函数,远远不能满足我们的需求。
3.3.1 .sortBy
_.sortBy会根据迭代器对输入的collection的每个数组元素进行计算后排序(升序)并生成一个新的数组,同时不会影响原collection的排序(这一点与原生的sort 不同)。
.sortBy有三个参数,与.forEach相同。
迭代器本身还有三个参数(value, index|key, collection),也与.forEach的迭代器相同。
//_.sortBy例子_.sortBy([1, 2, 3], function(n) { return Math.sin(n); //直接在迭代器中使用Math});// → [3, 1, 2]_.sortBy([1, 2, 3], function(n) { return this.sin(n); //在迭代器内用this绑定了Math}, Math);// → [3, 1, 2]var users = [ { 'user': 'fred' }, { 'user': 'pebbles' }, { 'user': 'barney' }];// 使用'user'作为快捷方式制定按'user'进行排序,简化了迭代器_.pluck(_.sortBy(users, 'user'), 'user');// → ['barney', 'fred', 'pebbles']
_.sorBy不只是对数组起作用,其实对字符串也一样起作用
_.sortBy('cBa').join('') //Bac ,如果要返回值还是字符串,需要用join函数_.sortBy('cBa')//[ 'B', 'a', 'c' ] ,缺省情况下 sortBy的返回值都是数组
排序之后动态添加数组元素,使用_sortedIndex,可以让新元素自动按拟定好的顺序排列进去,这是多体贴的设计啊!
var collection = [ 'Carl', 'Gary', 'Luigi', 'Otto' ]; var name = 'Luke'; //新添加一个元素进数组 collection.splice(_.sortedIndex(collection, name), 0, name);// _.sortedIndex会保持collection已有的次序 // →// [// "Carl",// "Gary",// "Luigi",// "Luke",// "Otto" // ]
3.3.2 _.sortByAll
与_.sortBy类似,但是可以对多个property name 或者多个迭代器进行排序,排序的顺序按照迭代器的排列顺序
var users = [ { 'user': 'fred', 'age': 48 }, { 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 42 }, { 'user': 'barney', 'age': 34 }];//先按'user'排序,再按'age'排序_.map(_.sortByAll(users, ['user', 'age']), _.values);// → [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]_.map(_.sortByAll(users, 'user', function(chr) { return Math.floor(chr.age / 10);}), _.values);// → [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
3.3.3 _.sortByOrder
类似于_.sortByAll,但是可以制定每一个迭代器的升降顺序,非常灵活!
var users = [ { 'user': 'fred', 'age': 48 }, { 'user': 'barney', 'age': 34 }, { 'user': 'fred', 'age': 42 }, { 'user': 'barney', 'age': 36 }];// 对'user'进行升序排列,对于'age'进行降序排列_.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values);// → [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
3.4 数据过滤和搜索
在已有数据集合中搜索和过滤数据是经常用到的功能,lodash提供了一系列工具来帮助我们实现数据的过滤和搜索。
3.4.1 _.where
.where是lodash当中最简单的过滤数据的方法,只有每一个条件都符合的数据才会被挑出来。
.where的好处是简单、精准,严格。
Note: This method supports comparing arrays, booleans, Date objects,
numbers, Object objects, regexes, and strings. Objects are compared by
their own, not inherited, enumerable properties. For comparing a
single own or inherited property value see _.matchesProperty.
注意:.where支持 数组, 布尔值, 日期, 数值, Object类型, 正则表达式,字符串的比较,Object类型只能比较其自身非继承的可枚举属性,要想比较单个Object或继承属性需要用 _.matchesProperty
var collection = [ { name: '路飞', age: 19, gender: '男' }, { name: '索隆', age: 21, gender: '男' }, { name: '娜美', age: 20, gender: '女' }, { name: '罗宾', age: 30, gender: '女' }]; _.where(collection, { age: 30, gender: '女' }); // → // [ // { name: '罗宾', age: 30, gender: '女' } // ]
3.4.2 .filter
_.filter有多种过滤方法
(1) _.matches
(2)_.matchesProperty
(3)_.property
//例子_.filter([4, 5, 6], function(n) { return n % 2 == 0;});// → [4, 6]var users = [ { 'user': 'barney', 'age': 36, 'active': true }, { 'user': 'fred', 'age': 40, 'active': false }];// using the `_.matches` callback shorthand_.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');// → ['barney']// using the `_.matchesProperty` callback shorthand_.pluck(_.filter(users, 'active', false), 'user');// → ['fred']// using the `_.property` callback shorthand_.pluck(_.filter(users, 'active'), 'user');// → ['barney']
_.filter还可以接受迭代器进行过滤
var collection = [ { type: '衬衣', size: 'L' }, { type: '裤子', size: 'S' }, { type: 'T恤', size: 'XL' }, { type: '鞋子', size: 'M' }];_.filter(collection, function(item) { return item.size === 'L' || item.size === 'M';});// → // [// { type: "衬衣", size: "L" },// { type: "鞋子", size: "M" }// ]
3.4.3 .reject
当你不知道从集合里面直接选出什么,但是却明确知道不要选什么的时候,你可以用.reject来处理了。
//例子中把 enabled:false的数据筛掉了var collection = [ { name: '冰与火之歌', enabled: true }, { name: '星球大战', enabled: false }, { name: '指环王', enabled: false }, { name: '哈里波特', enabled: true }]; _.reject(collection, { enabled: false }); // → // [ // { name: "冰与火之歌", enabled: true }, // { name: "哈里波特", enabled: true } // ]
3.5 只找一条符合要求的数据
有时候你并不需要找到所有符合条件的数据,而是只要第一条就够了,那么就用find系列(find、findLast、findWhere),find系列的参数和filter一样,但是返回值不再是数组,而是一个符合条件的元素。如果没找到符合条件的,那就返回undefined
3.5.1_.find
找出第一条符合条件的数组元素(即从数组的左侧找起)
var users = [ { 'user': '钱夫人', 'age': 36, 'active': true }, { 'user': '阿土伯', 'age': 45, 'active': false }, { 'user': '孙小美', 'age': 20, 'active': true }, { 'user': '糖糖', 'age': 20, 'active': true }];_.result(_.find(users, function(chr) { return chr.age < 40; //找出第一个age小于40的元素}), 'user');// → '钱夫人'
3.5.2_.findLast
找出最后一条符合条件的数组元素(即从数组的右侧找起)
_.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1;});// → 3
3.5.3 _.findWhere
参数source是个object,严格按照source来查找匹配的第一项
var users = [ { 'user': '钱夫人', 'age': 36, 'active': true }, { 'user': '阿土伯', 'age': 45, 'active': false }];_.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');// → '钱夫人'_.result(_.findWhere(users, { 'age': 45, 'active': false }), 'user');// → '阿土伯'
3.6 “集合”改造(Transforming collections)
lodash有一批工具用于把Collection(集合)改造为新的数据结构,而且还有工具把两个或更多的集合合并到一个集合里去。这些工具可以把我们程序狗从一些繁重而重复的劳动中解放出来,并且让我们的代码更加简介易懂。
3.6.1_.groupBy
在集合中,往往有些元素的某项属性的值是相同的,那么我们就可以这项属性为key进行分组,从而产生一个新的JSON对象,这个JSON对象的key就是被分组的值。
_.groupBy有三个参数,第一个参数是要处理的collection,第二个参数是迭代器(以匿名函数的形式出现),第三个参数是 The this binding of iteratee(可以理解为迭代器里的this绑定的方法)。
groupBy与indexBy的区别在于:groupBy聚合的值以数组形式出现,indexBy获得的值以Object形式出现。
//比如下面这个例子:以size作为分组的依据,得到的新JSON中有"S"和"M"两个Keyvar collection = [ { name: 'Lori', size: 'S' }, { name: 'Johnny', size: 'M' }, { name: 'Theresa', size: 'S' }, { name: 'Christine', size: 'S' } ];_.groupBy(collection, 'size');// {// S:[// { name: "Lori", size: "S" },// { name: "Theresa", size: "S" },// { name: "Christine", size: "S" }// ]// M: [// { name: "Johnny", size: "M" }// ]// }
//也可以用迭代器进行分类,并用迭代器指定key的名称var collection = [ { name: '小黄', age: 20 }, { name: '老李', age: 50 }, { name: '老朱', age: 67 }, { name: '大蒋', age: 39 } ]; _.groupBy(collection, function(item) { return item.age > 65 ? 'retired' : 'working';});// →// {// [// working: [// { name: "小黄", age: 20 },// { name: "老李", age: 50 },// { name: "大蒋", age: 39 }// ],// retired:[// { name: "老朱", age: 67 }// ]// }
3.6.2 min,max
_.min(collection, [iteratee], [thisArg])
_.max(collection, [iteratee], [thisArg])
找出那个符合条件的最小(或者最大)的数组元素。
var collection = [ { name: 'Douglas', age: 52, experience: 5 }, { name: 'Karen', age: 36, experience: 22 }, { name: 'Mark', age: 28, experience: 6 }, { name: 'Richard', : age: 30, experience: 16 } ]; //用Key来查找 _.min(collection, 'age'), // → { name: "Mark", age: 28, experience: 6 } //用迭代器来查找 _.max(collection, function(item) { return item.age + item.experience; }); // → { name: "Karen", age: 36, experience: 22 }
3.7 集合的扁平化和压缩
集合中数据有时是嵌套结构的,我们需要对它们进行扁平化处理;
而有些时候,集合中的元素包含一些没用的值,我们可以对其进行压缩处理。
通过扁平化和压缩,我们可以得到更加精炼的数据结构,以便进行分析和展示。
//以下是个多种工具结合进行处理的例子:var collection = [ { employer: 'Lodash', employees: [ { name: 'Barbara' }, { name: 'Patrick' }, { name: 'Eugene' } ]}, { employer: 'Backbone', employees: [ { name: 'Patricia' }, { name: 'Lillian' }, { name: 'Jeremy' } ]}, { employer: 'Underscore', employees: [ { name: 'Timothy' }, { name: 'Bruce' }, { name: 'Fred' }]} ];//1、用.pluck挑出需要的Key及其value//注意pluck拔出的数据是个二维数组,所以还要用flatten将二维数组降为一维数组var employees = _.flatten(_.pluck(collection, 'employees'));//2、通过迭代器筛选出要使用的数据_.filter(employees, function(employee) { return (/^[bp]/i).test(employee.name); }); // → // [ // { name: "Barbara" }, // { name: "Patrick" }, // { name: "Patricia" }, // { name: "Bruce" } // ]
3.8 鉴别部分或全部的集合元素 some、every
3.8.1_.some
some的作用是判断只要集合中有符合要求的属性,就返回true,否则返回false
_.some([null, 0, 'yes', false], Boolean);// → truevar users = [ { 'user': 'barney', 'active': true }, { 'user': 'fred', 'active': false }];// using the `_.matches` callback shorthand_.some(users, { 'user': 'barney', 'active': false });// → false// using the `_.matchesProperty` callback shorthand_.some(users, 'active', false);// → true// using the `_.property` callback shorthand_.some(users, 'active');// → true
3.8.2_.every
_.every则是判断是否集合中每一个元素都包含
var collection = [ { name: 'Jonathan' }, { first: 'Janet' }, { name: 'Kevin' }, { name: 'Ruby' } ];if (!_.every(collection, 'name')) { return '缺少name属性;}// → "缺少name属性"
lodash Collection小结:
1、数组(Array)肯定是集合(Collection),所以所有的Colleciton方法都适用于数组;
2、集合不一定都是数组;
3、本节中还有少量的Collection方法没有提及,如map、reduce、reduceRight将在 Map/Reduce篇中介绍。
- lodash 中文学习拾零之 Collection篇
- lodash 中文学习拾零之Array篇
- lodash 中文学习拾零之 Chain篇
- lodash 中文学习拾零之 Object篇
- lodash 中文学习拾零之 Map/Reduce篇
- lodash "collection" methods lodash中文翻译更新中
- lodash学习笔记之Array方法
- centos学习 拾零之如何安装rar
- Lodash 中文文档
- 拾零-中文问题
- centos学习 拾零之如何关闭防火墙步骤
- lodash "Array" methods中文 lodash中文 更新中
- lodash 之 Chain篇 显试调用与隐性调用
- Java学习篇之---Collection接口
- lodash
- lodash
- lodash
- Lodash
- CMD 批处理 选择器
- 理想程序员
- 排列组合算法
- android中对/data/data/<package name>/files下文件的读写操作
- SET Transaction Isolation Level Read语法的四种情况
- lodash 中文学习拾零之 Collection篇
- Android内存分析工具(六):开源项目Emmagee
- 如何通过SSH反向隧道,访问NAT后面的Linux服务器?
- 如何让计划任务执行时显示CMD窗口
- 【java】反射机制
- 《将博客搬至CSDN》
- tableView将cell底部横线填满
- java复习笔记之自定义函数泛型
- 770 仿射密码【暴力枚举】