一、reduce方法的作用
reduce方法是ruby中的一个重要的方法,也叫inject方法(Ruby1.9之前reduce方法不可用)
reduce方法是一个可以将一个数据结构转换成另一种结构的折叠函数。因此,reduce可以提升性能,它的性能要高于逐个遍历的迭代器,比如map、select等等
二、reduce方法的使用说明
-
reduce方法的消息接收者对应的类必须要引入Enumerable模块,因为reduce方法是Enumerable模块的方法。
-
reduce方法后跟代码块,代码块的目的是创建并返回下一个适用于下一次代码块迭代的累加器
-
reduce方法的参数值就是累加器的初始值,这个参数也是发给代码块的第一个参数,第二个参数是要遍历的原始集合中的元素。
-
如果原始集合为空,那么代码块将不会被执行
-
每次迭代后,reduce会丢弃上次迭代的累加器,保留代码块返回值作为新的累加器。reduce方法最终返回的是累加器最终的值
-
代码块可以改写成symbol格式,因此在使用reduce方法时,可以使用方法的symbol格式,每个迭代reduce都使用符号作为消息名称发送消息给累加器,同时将当前元素作为参数。
三、reduce方法的使用案例
(一)求和
#代码块形式
[*1..100].reduce(0) {|sum, i| sum + i}
符号形式
[*1..100].reduce(0,&:+)
#或
[*1..100].reduce(0,:+)
(二)构建hash
arr = [[1,true],[2,true]]
arr.to_h
=> {1=>true, 2=>true}
#也可以用Hash的[]方法
Hash[arr]
=> {1=>true, 2=>true}
#或
array = [1,2]
Hash[array.map {|x| [x,true]}]
=> {1=>true, 2=>true}
上述写法可以用reduce来简化
array.reduce({}) do |h, element|
#update方法可以直接更新和添加键对应的值
h.update(element => true)
end
=> {1=>true, 2=>true}
nums = [[1,true], [2,false]]
nums.reduce({}) do |h, element|
h.update(element.first => element.last)
end
=> {1=>true, 2=>false}
(三)筛选元素
比如,我们要从数组中筛选出年龄大于20的用户,并以数组形式返回它们的姓名
users.select {|u| u.age > 20}.map(&:name)
这样写不够高效因为先用select遍历了数组选出年龄大于20的用户,返回新数组,然后这个数组有进行了map循环,又生成了一个数组
可以用reduce来实现。因为reduce是折叠函数,因此它的性能要高于map等迭代器
users.reduce([]) do |names, user|
names << user.name if user.age > 20
#始终返回names作为下一次迭代的累加器,保证条件为假时,也能返回names作为累加器,这个累加器默认的就是reduce的参数[]
names
end
四、参考资料
1.《Effective Ruby》第19条--了解如何通过reduce方法折叠集合
网友评论