可枚举模块。 Enumerable mixin 是含有几组遍历与查寻方法的集合类,而且它还有排序的能力。
如果你希望自己的类也具有集合类这么多优秀的特点,那么这个类必须提供一个 each 方法,在这个方法内,它产生连续的集合成员。即依次返回你自己集合类的元素。然后再在你的类中混合插入 Enumerable 模块,你的类就可支持 map 、 include? 、 find_all? 等方法了。若你集合内的元素再支持 <=> 方法,即集合内的元素混合插入了 Comparable 模块,那么这个集合也可以得到 min 、 max 、 sort 等方法。
实例方法:
(1) enum.all? [{|obj| block } ] => true or false enum.any? [{|obj| block } ] => true or false 将集合内的每个元素传递给块。即依次为集合内的各个元素来执行块的内容。当所有元素为真时, all 返回 true 。当所有元素为假时, any 返回 false 。如果忽略了 block 块,则 Ruby 会偷偷地添加一个 {|obj|obj} 块。
例如:
%w{ ant bear cat}.all? {|word| word.length >= 3} #=> true
%w{ ant bear cat}.all? {|word| word.length >= 4} #=> false
[ nil, true, 99 ].all? #=> false
%w{ ant bear cat}.any? {|word| word.length >= 3} #=> true
%w{ ant bear cat}.any? {|word| word.length >= 4} #=> true
[ nil, true, 99 ].any? #=> true
(2) enum.collect {| obj | block } => array enum.map {| obj | block } => array 依次为 enum 内的每个元素执行块 block 的内容,并将结果存入一个新数组中,最后返回该数组。
例如:
(1..4).collect {|i| i*i } #=> [1, 4, 9, 16]
(1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
省略块时,会执行 obj.collect {|item| item} 这等同于 Enumerable#to_a 。
注: collect 有收集,采集的含义。
(3) enum.each_with_index {|obj, i| block } → enum 对于 enum 内的每个条目,使用元素及其索引进行循环操作的迭代器,即使用两个参数调用块。并返回 self 。
例如:
hash = Hash.new
%w(cat dog wombat).each_with_index {|item, index|
hash[item] = index }
hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
(4) enum.detect(ifnone = nil) {| obj | block } => obj or nil enum.find(ifnone = nil) {| obj | block } => obj or nil 传递 enum 内的每个元素给块 block 进行计算,返回计算值首次为真的那个元素。若块的计算始终都不为真的话,则计算 ifnone 部分 ( 如果有的话 ) 并返回它的值,或者返回 nul 。
例如:
(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
注: detect 和 find 单词都有查明真相的意思,用在这个方法上,是因为它要查出每个元素经过计算后的真相,即是否为真。
(5) enum.find_all {| obj | block } => array enum.select {| obj | block } => array 在使用元素进行块计算时,若计算值为真,则把该元素存入数组,最后返回该数组。若块的计算始终都不为真时,则返回空数组。
例如:
(1..10).find_all {|i| i % 3 == 0 } #=> [3, 6, 9]
注: select 有挑选的意思。把计算后为真的元素挑选出来。
(6) enum.grep(pattern) => array enum.grep(pattern) {| item | block } => array 若 pattern === item ,则把该元素存入数组,最后返回该数组,若带块调用时,则会依次为所有满足上述条件的元素来执行块的内容,并把计算结果存入到数组,最后返回该数组。若没有符合条件的元素时,返回空数组。
例如:
(1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
c = IO.constants
c.grep(/SEEK/) #=> ["SEEK_END", "SEEK_SET", "SEEK_CUR"]
res = c.grep(/SEEK/) {|v| IO.const_get(v) }
res #=> [2, 0, 1]
注: grep 这个单词在 UNIX 中是一个工具程序。可用做文件内的字符串查找。
(7) enum.inject(initial) {| memo, obj | block } => obj enum.inject {| memo, obj | block } => obj 在每一步骤中, memo 要被设置为由块计算后返回的值。首先,用 initial 初始化 memo 的值,并将 memo 与 obj 参数传递给块进行计算。然后将上步块计算后的值赋值给 memo 后,再继续计算块,以此类推。
其中, enum 集合中的每个元素依次赋值给 obj 。而 memo 的初始是 initial ,尔后则是由 block 块计算出来的值。这样一直循环到 enum 的最后元素,并将最后的块的计算结果返回。
若省略了初始值 initial 的话,开始时会把第 1 和第 2 个元素传递给块。 此时,若只有 1 个元素时,将直接返回首元素,而不会执行块。 若没有元素,则返回 nil 。
例如:求和的计算
p [1,2,3,4,5].inject(0) {|result, item| result + item } #=> 15
这等同于
result = 0
[1,2,3,4,5].each {|v| result += v }
p result #=> 15
再如:
# 查找最长的单词
longest = %w{ cat sheep bear }.inject do |memo,word|
memo.length > word.length ? memo : word
end
longest #=> "sheep"
# 查找最长单词的长度。
longest = %w{ cat sheep bear }.inject(0) do |memo,word|
memo >= word.length ? memo : word.length
end
longest #=> 5
注:这个方法之所以用 inject 这个单词,是因为这个方法有个注射动作,即将 initial 及后来的块计算结果注入到 memo 中。
(8) enum.include?(obj) => true or false enum.member?(obj) => true or false 若 obj== 某元素时,返回真。
(9) enum.max => obj enum.max {|a,b| block } => obj
enum.min => obj enum.min {| a,b | block } => obj 返回最大与最小的元素。不带块的第一种形式是假设 enum 的所有元素都实现了 Comparable 模块。第二种形式块使用 <=> 来判断 enum 内各个元素的大小。通常要求该块返回下列各整数值:当 a>b 时返回正整数, a==b 时返回 0 ,而 a<b 时返回负整数。若该块返回了一个非整数值时,会引发 TypeError 异常。
例如:
a = %w(albatross dog horse)
a.min #=> "albatross"
a.min {|a,b| a.length <=> b.length } #=> "dog"
a.max #=> "horse"
a.max {|a,b| a.length <=> b.length } #=> "albatross"
(10) enum.partition {| obj | block } => [ true_array, false_array ] 若对某元素执行块的结果为真,则把该元素归入第一个数组;若为假则将其归入第二个数组 , 最后生成并返回一个包含这两个数组的新数组。
例如:
(1..6).partition {|i| (i&1).zero?} #=> [[2, 4, 6], [1, 3, 5]]
注:硬盘的分区就使用这个单词。只是没有想到我们要操作的一些对象,也可以被“分区”的。
(11) enum.reject {| obj | block } => array 对 enum 内的各元素依次传入块中进行计算,若计算值为假则将该元素存入数组,最后返回该数组。
例如:
(1..10).reject {|i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
注: reject 有不合格者,不合格品的意思。
(12) enum.sort => array enum.sort {| a, b | block } => array 对所有元素进行升序排列后返回这个新的数组。若不带块时,将以 <=> 方法的比较结果为基础进行排序。如果想借用 <=> 之外的方法进行排序时,可以指定一个块。此时将以块的计算结果为基础进行排序。通常要求该块返回下列各值:当 a>b 时返回正整数, a==b 时返回 0 ,而 a<b 时返回负整数。若该块返回了一个非整数值时,会引发 TypeError 异常。
Enumerable#sort 所进行的是不稳定的排序 (unstable sort) 。
注:排序后,若相等的元素的位置并未改变的话,这种排序就是 " 稳定的排序 (stable sort)" 。
例如:
%w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
(1..10).sort {|a,b| b <=> a} #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]