reduce是Enumerable的方法,reduce和inject是别名方法。它是一个可以将一个数据结构转换成另外一种结构的折叠函数。

reduce方法的特点是返回一个累计器,这个累加器是从块中进行返回,比如下面的代码中

#返回累加器是sum+element,这个值会赋予给sum
(1..10).reduce(0){|sum, element| sum+element} 

#返回的累加器是example,这个返回的累加器即使最后的返回值example,这个example会重新赋予给参数example,作为下一次使用
result = demo.reduce([]) do |example, value|
  example << value[2] if (value[1] > 15 && value[0] == "jayzen")
  example
end

使用reduce来实现累加

#使用初始值
(1..10).reduce(0){|sum, element| sum+element} #55

上面的代码进行解释,当使用初始值为0时,里面的参数sum为0,element为1,返回值为1+0=1,返回值作为下一次累加值的初始值,即是下一次累加值开始时,sum为1,element为2

#没有初始值
(1..10).reduce{|sum, element| sum+element} #55

如果没有初始值,则在第一次进行累计计算的时候sum是该遍历对象的第一个数,即1,element是该遍历对象的第二个数2,后面的执行方式如上所示。

#直接使用symbol方法
(1..10).reduce(:+) #55
#symbol中也可以指定初始值
(1..10).reduce(1:+) #56
#可以添加&前缀,但是效果一致,只是看起来和each,map方法里面的使用方式一致
(1..10).reduce(1,&:+) #56
#[1,2,3].map(&:to_s), ["1", "2", "3"]

刷选出长度最长的值的字符

longest = %w{ cat sheep bear }.inject do |memo, word|
   memo.length > word.length ? memo : word
end
longest #=> "sheep"  #如果两个字符的长度一样,则为数组中符号靠后的值

将数组转换为hash,注意hash中的update方法和merge!的功能是一致的,会改变hash的值

#通过reduce将数组转化为hash
(1..3).to_a.reduce({}){|hash, element| hash.update(element=> true)} #{1=>true, 2=>true, 3=>true}

#通过each方法将数组转化为hash
hash = {}
(1..3).to_a.each { |element| hash[element] = true }
p hash #{1=>true, 2=>true, 3=>true}

reduce的优越性

#获取二维数组如下
#demo = [["jayzen", 20, "hangzhou"], ["jay", 30, "suzhou"], ["zen", 40, "quzhou"], ["jayzen", 16, "mingzhou"]]

#需要执行如下的操作,满足年龄大于15并且姓名为“jayzen”,最后取出地址的数组值
p demo.select{|value| value[1] > 15 && value[0] == "jayzen"}.map{|value| value[2]} #["hangzhou", "mingzhou"]

#上面的代码需要遍历两次数组,而使用reduce方法只要遍历一次数组,更高效
#reduce方法需要确保返回一个累加器,下面实现了一个新的累加器
result = demo.reduce([]) do |example, value|
  example << value[2] if (value[1] > 15 && value[0] == "jayzen")
  example
end
p result #["hangzhou", "mingzhou"]

#只用map方法也可以实现
demo.map{|value| value[2] if (value[1] > 15 && value[0] == "jayzen")}.compact #["hangzhou", "mingzhou"]

results matching ""

    No results matching ""