Enumerable

为那些进行循环操作的类准备的Mix-in. 本模块中定义的方法都用到了each,因此在那些包含本模块的类中,必需预先定义了each才行.

方法:

all?
all? {|item| ... }

ruby 1.7 特性:

当所有元素都为真时,返回true. 若某元素为假时, 立即返回false.

ruby 1.8 特性: 若带块调用时, 会依次为各个元素来执行块的内容, 若所有的结果都为真,则返回true. 一旦块返回假时, 立即返回false.

p [1,2,3].all? {|v| v > 0}   # => true
p [1,2,3].all? {|v| v > 1}   # => false
any?
any? {|item| ... }

ruby 1.7 特性:

当所有元素都为假时,返回false. 一旦某元素为真时, 立即返回true.

ruby 1.8 特性: 若带块调用时, 会依次为各个元素来执行块的内容, 若所有的结果都为假,则返回false. 一旦块返回真时, 立即返回true.

p [1,2,3].any? {|v| v > 3}   # => false
p [1,2,3].any? {|v| v > 1}   # => true
collect {|item| ... }
map {|item| ... }

依此为各元素执行块的内容,并将结果存入数组,最后返回该数组.

省略块时,会执行

obj.collect {|item| item}

这等同于Enumerable#to_a.

each_with_index {|item,index| ... }

使用元素及其索引进行循环操作的迭代器.

返回self.

find([ifnone]) {|item| ... }
detect([ifnone]) {|item| ... }

在使用元素进行块的计算时, 返回计算值首次为真的那个元素. 若块的计算值始终都不为真时, 则计算ifnone部分(若有的话),并返回nil. (ruby 1.7 特性: 返回ifnone的计算值.)

ifnone可以是字符串或带call方法的对象(例如Proc).

[1,2,3].find("raise") {|v| v > 4}
# => -:1: unhandled exception

ruby 1.7 特性: ifnone不能是字符串了.

find_all {|item| ... }
select {|item| ... }

在使用元素进行块的计算时,若计算值为真则把该元素存入数组,最后返回该数组. 若块的计算值始终都不为真时,则返回空数组.

grep(pattern)
grep(pattern) {|item| ... }

pattern === item,则把该元素存入数组,最后返回该数组. 若带块调用时, 则会依次为所有满足上述条件的元素来执行块的内容, 并把计算结果存入数组,最后返回该数组. 若没有符合条件的元素时, 返回空数组.

inject([init]) {|result, item| ... } ((<ruby 1.7 特性>))

开始时,把初始值initself的首元素当做块参数来计算块的内容. 从第2次循环开始, 将把上次的块的计算结果和self的下个元素当做块参数来计算块. 这样一直循环到最后的元素, 返回最后的块的计算结果.

若没有元素,则返回init.

若省略了初始值init的话, 开始时会把第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
member?(val)
include?(val)

val==某元素时,返回真.

max

返回最大的元素. 该方法假定所有元素都是可以使用<=>方法来进行比较的.

max {|a, b| ... }

以块的计算结果来判断各个元素的大小, 并返回最大的元素.

通常要求该块返回下列各整数值: 当a>b时返回正整数,a==b时返回0,而a<b时返回负整数. 若该块返回了一个非整数值时, 会引发TypeError异常.

max_by {|item| ... } ((<ruby 1.9 特性>))

<=>来比较块的计算值, 并返回最大的元素.

max与max_by间的差别就如同sort与sort_by间的不同一样. 详情请参考sort_by.

min

返回最小的元素. 该方法假定所有元素都是可以使用<=>方法来进行比较的.

min {|a, b| ... }

以块的计算结果来判断各个元素的大小, 并返回最小的元素.

通常要求该块返回下列各整数值: 当a>b时返回正整数,a==b时返回0,而a<b时返回负整数. 若该块返回了一个非整数值时, 会引发TypeError异常.

min_by {|item| ... } ((<ruby 1.9 特性>))

<=>来比较块的计算值, 并返回最小的元素.

min与min_by间的差别就如同sort与sort_by间的不同一样. 详情请参考sort_by.

partition {|item| ... } ((<ruby 1.7 特性>))

若对某元素执行块的结果为真, 则把该元素归入第一个数组;若为假则将其归入第二个数组,最后生成并返回一个包含这两个数组的新数组.

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0].partition { |i| i % 3 == 0 }
 #=> [[9, 6, 3, 0], [10, 8, 7, 5, 4, 2, 1]]
reject {|item| ... }

依此为各元素计算块的内容, 若计算值为假则将该元素存入数组,最后返回该数组.

sort
sort {|a, b| ... }

对所有元素进行升序排列后返回这个新的数组.

若不带块时, 将以<=>方法的比较结果为基础进行排序.

如果想借用<=>之外的方法进行排序时,可以指定一个块. 此时将以块的计算结果为基础进行排序. 通常要求该块返回下列各值: 当a>b时返回正整数,a==b时返回0,而a<b时返回负整数. 若该块返回了一个非整数值时, 会引发TypeError异常.

Enumerable#sort 所进行的是不稳定的排序(unstable sort)。

注: 排序后,若相等的元素的位置并未改变的话,这种排序就是"稳定的排序(stable sort)".

sort_by {|item| ... } ((<ruby 1.7 特性>))

<=>方法来比较块的计算值, 并对self进行升序排列,最后生成并返回新生成的数组. 这基本上等同于

class Array
  def sort_by
    self.collect {|i| [yield(i), i] }.
       sort {|a,b| a[0] <=> b[0] }.
       collect! {|i| i[1]}
  end
end

在下例中并未使用sort_by, 每次进行比较时都会执行downcase. 所以,若downcase的运行速度较慢时, 将会对sort的速度造成致命的影响.

p ["BAR", "FOO", "bar", "foo"].sort {|a,b| a.downcase <=> b.downcase }

另一方面,下例中使用了sort_by,此时downcase的运行次数取决于元素个数.

p ["BAR", "FOO", "bar", "foo"].sort_by {|v| v.downcase }

下例中检验了它的执行次数,供您参考.

class Integer
  def count
    $n += 1
    self
  end
end

ary = []
1.upto(1000) {|v| ary << rand(v) }

$n = 0
ary.sort {|a,b| a.count <=> b.count }
p $n          # => 18200

$n = 0
ary.sort_by {|v| v.count }
p $n          # => 1000

Enumerable#sort_by 是不稳定的排序(unstable sort)。

注: 排序后,若相等的元素的位置并未改变的话,这种排序就是"稳定的排序(stable sort)".

您可以像下例这样来实现稳定排序.

i = 0
ary.sort_by {|v| [v, i += 1] }
to_a
entries

返回包含所有元素的数组.

zip([ary1[, ary2[, ...]]])
zip([ary1[, ary2[, ...]]]) {|v1, v2, ...| ...}

ruby 1.7 特性:

生成并返回一个由self和参数数组中的元素构成的数组的数组. 新数组的元素个数取决于self中的元素数.

p [1,2,3].zip([4,5,6], [7,8,9])
=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

p [1,2].zip([:a,:b,:c], [:A,:B,:C,:D])
=> [[1, :a, :A], [2, :b, :B]]

p (1..5).zip([:a,:b,:c], [:A,:B,:C,:D])
=> [[1, :a, :A], [2, :b, :B], [3, :c, :C], [4, nil, :D], [5, nil, nil]]

带块调用时, 将把各数组作为参数传递给块,然后计算该块. 通常zip会返回nil.

p [1,2,3].zip([4,5,6], [7,8,9]) {|ary|
  p ary
}
=> [1, 4, 7]
   [2, 5, 8]
   [3, 6, 9]
   nil