使用方法

最普通的

ary = ["a", "b", "c"]
ary.each{|obj| p obj}

带索引的

ary = ["a", "b", "c"]
ary.each_with_index do |obj, idx|
    p [obj, idx]
end

hash

address = {name: "Aaron Ryuy", tel: "15007160010"}
address.each do |key, value|
  p [key, value]
end

#=> [:name, "Aaron Ryuy"]
#=> [:tel, "15007160010"]

替代异常

File.open("sample.txt") do |file|
    file.each_line do |line|
        p line
    end
end

#等价于

file = File.open("sample.txt")
begin
    file.each_line do |line|
        p line
    end
ensure
    file.close
end

排序

a<=>b的结果

条件 返回值
a < b时 -1 (比0小)
a == b时 0
a > b时 1 (比0大)
array = ["ruby", "Perl", "PHP", "Python"]
sorted = array.sort
#sorted = array.sort{ |a, b| a<=>b }

p sorted
#=> ["PHP", "Perl", "Python", "ruby"]

sorted = array.sort{ |a, b| a.length<=>b.length }
p sorted
#=> ["PHP", "ruby", "Perl", "Python"]

sorted = array.sort_by{ |item| item.length }
p sorted
#=> ["PHP", "ruby", "Perl", "Python"]

定义带块的方法

def hello
  (1..5).each do |i|
    if block_given?
      p yield(i)
    else
      p i
    end
  end
end

hello
#=> 1 2 3 4 5

hello{|i| i*2}
#=> 2 4 6 8 10

控制块的执行

方法 意义
break 块中执行break,会立即返回,没有返回值。
break 0 返回 0
next 中断当前处理,返回nil, 继续执行下面的处理
next 0 返回 0
redo 不要用,容易死循环

封装为对象

hello = Proc.new do |name|
  p "hello, #{name}."
end

hello.call "Aaron"

局部变量与块变量

块变量是只能在块内部使用的变量,不能覆盖外部的局部变量

x = 1
y = 2
ary = [1, 2, 3]

ary.each do |x|
  #这里的x是块变量,是不会改变外部的x的
  #y会变为3
  y = x
end

p [y, x]
#=> [3, 1]
x = 1
ary = [1, 2, 3]

ary.each do |x|
  y = x
end

p [y, x]
#=> 报错,因为外部没有y
x = y = z = 0
ary = [1, 2, 3]

# ; 后面的y为块局部变量,不会影响外部的变量y
ary.each do |x; y|
  y = x
  z = x
  p [x, y, z]
end

p [x, y, z]
#=> [1, 1, 1]
#=> [2, 2, 2]
#=> [3, 3, 3]

#=> [0, 0, 3]
=begin
块内部,没有对x进行赋值,所以不会影响到外部的x
块内部,虽然对y进行了赋值,但是y是块局部变量,不影响外部的y
块内部,对z进行了赋值,所以是最后一次循环的结果3
=end

将块封装为对象

hello = Proc.new do |name|
    p "Hello, #{name}."
end

hello.call("Aaron")

&block就是个Proc对象

def call_each(ary)
    ary.each do |item|
        p item
    end
end

call_each [1, 2, 3]
def call_each(ary, &block)
    #这里的&block就是下面块里的代码,所以与上面等价
    ary.each &block
end

call_each [1, 2, 3] do |item|
    p item
end