Ruby's Enumerable Module and yield method

简介:
Hash, Array, Range, Set 类的对象为什么可以使用include?, min, max等方法, 原因是这些CLASS包含了Enumerable模块.
这个模块的详细介绍可以在Ruby Core API Reference中查询.
下面对某些方法举例说明 : 
测试版本1.9.3-p0
一、内建类型的Enumerable方法调用
1. min
a = Array.new(['z','abc','bc','d1','efg'])
p(a.min)   #=>"abc" , 默认情况下min 判断的是ascii码
p(a.min{
 |x|
 x.length
 })  #=>"z" , 这里判断的是字符长度.


2. max
a = {'z'=>'digoal',
 'abc'=>'francs',
 'bc'=>'dage',
 'd1'=>'hank',
 'efg'=>'new'}
p(a) #=>{"z"=>"digoal", "abc"=>"francs", "bc"=>"dage", "d1"=>"hank", "efg"=>"new"}
p(a.max) #=>["z", "digoal"]
p(a.max{
 |x|
 x.length
 }) #=>["efg", "new"] , 这里判断的是hash key的字符长度.


3. sort
a = {'z'=>'digoal',
 'abc'=>'francs',
 'bc'=>'dage',
 'd1'=>'hank',
 'efg'=>'new'}
p(a) #=> {"z"=>"digoal", "abc"=>"francs", "bc"=>"dage", "d1"=>"hank", "efg"=>"new"}
p(a.sort) #=> [["abc", "francs"], ["bc", "dage"], ["d1", "hank"], ["efg", "new"], ["z", "digoal"]] , 默认按ASCII排序
p(a.sort{
 |x,y|
 x[0].length <=> y[0].length
 }) #=> [["z", "digoal"], ["d1", "hank"], ["bc", "dage"], ["abc", "francs"], ["efg", "new"]]  , 这里按照Hash key的长度排序
p(a.sort{
 |x,y|
 x[1].length <=> y[1].length
 }) #=> [["efg", "new"], ["d1", "hank"], ["bc", "dage"], ["abc", "francs"], ["z", "digoal"]] , 这里按照Hash value的长度排序


4. collect
a = [1,2,3,4,5,6]
b = a.collect {
 |x|
 x * x
}
p(a) #=> [1, 2, 3, 4, 5, 6]
p(b) #=> [1, 4, 9, 16, 25, 36] , collect方法重新构造一组数据.


5. include?
a = [1,2,3,4,5,6]
p(a.include?(1)) #=> true , 判断是否包含1
p(a.include?(7)) #=> false , 判断是否包含7


二、自定义CLASS中包含Enumerable模块举例 : 
class MyClass
 include Enumerable # 这个指包含Enumerable模块
 def initialize( someItems )
  @items = someItems
 end

 def each # 要在自定义类中使用Enumerable模块中的方法, 必须写一个each 方法, 告诉其他要调用的Enumerable方法每次传什么值进去.
  @items.each{
                       |i|
   yield(i)  # yield方法里面的参数, 就是表示其他要调用的Enumerable方法每次传什么值进去.这里每次传的就是i
  }
 end
end

a = MyClass.new(['c','bda1a','baz','ce','zwfg'])
p(a) #=> #<MyClass:0x1ef0db0 @items=["c", "bda1a", "baz", "ce", "zwfg"]>
p(a.sort) #=> ["baz", "bda1a", "c", "ce", "zwfg"]

class MyClass
 include Enumerable
 def initialize( someItems )
  @items = someItems
 end

 def each
  @items.each{
   |i|
   yield(i.to_s.length) #这里每次传的是i.to_s.length
  }
 end
end

a = MyClass.new(['c','bda1a','baz','ce','zwfg'])
p(a) # => #<MyClass:0x1e90c90 @items=["c", "bda1a", "baz", "ce", "zwfg"]>
p(a.sort) # => [1, 2, 3, 4, 5]

# 自定义类型中如果没有定义each方法, 但是调用了Enumerable中的方法会报错, 例如 : 
`sort': undefined method `each' for #<MyClass:0x1ebfb08 @items=["c", "bda1a", "baz", "ce", "zwfg"]> (NoMethodError)

【参考】
Ruby Core API Reference : Enumerable
The Book of Ruby : Page 100 - 105
目录
相关文章
|
5月前
|
Ruby
|
5月前
|
Ruby
|
5月前
|
Ruby
|
5月前
|
Java C++ Ruby
|
C# Ruby 开发者
ruby学习笔记(5)-模块module的运用
ruby中的module与.net中的namespace有点类似,可以用来区分同名但属于不同开发者(或组织)的代码。 下面的代码,定义了一个Me模块,里面的sqrt与Math模块中的sqrt重名,另外还有一个重名常量PI #定义一个模块(有点类似.
908 0
|
5月前
|
Ruby
|
5月前
|
JSON 数据格式 Ruby
|
5月前
|
调度 Ruby