0

我很容易对迭代感到困惑 - 谁能告诉我这段代码到底做了什么?朋友和家人是哈希,语言是 Ruby。

friends.each { |x| puts "#{x}" } 
family.each { |x, y| puts "#{x}: #{y}" }
4

2 回答 2

4
friends.each { |x| puts "#{x}" } 
family.each { |x, y| puts "#{x}: #{y}" }

第一个基本上相当于:

x = [friends.keys[0], friends.values[0]]
puts "#{x}"
x = [friends.keys[1], friends.values[1]]
puts "#{x}"
x = [friends.keys[2], friends.values[2]]
puts "#{x}"
# ...
x = [friends.keys[n], friends.values[n]]
puts "#{x}"

第二:

x = family.keys[0]
y = family.values[0]
puts "#{x}: #{y}"
x = family.keys[1]
y = family.values[1]
puts "#{x}: #{y}"
x = family.keys[2]
y = family.values[2]
puts "#{x}: #{y}"
# ...
x = family.keys[n]
y = family.values[n]
puts "#{x}: #{y}"

任何时候你有类似{ |...| ... }do |...|; ...; end在一个方法之后的东西,你都在创建所谓的块。此块被传递给方法,该方法可以将yield参数传递给该块。Array#each将使用每个元素调用块;Hash#each会通过[key, value]的。

当然,你可以做一些完全不同的事情,比如:

def test
  yield('oh my')
  yield('i really')
  yield('like blocks')
end
test { |a| puts a }

哪个输出

oh my
i really
like blocks

如果您yield将数组分配给块,则可以将其分配给多个或单个参数。

def test
  yield(['oh', 'my'])
  yield(['i', 'really'])
  yield(['like', 'blocks'])
end
test { |a, b| puts "#{a}-#{b}" }

哪个输出

oh-my
i-really
like-blocks

或者,如果您只接受块中的单个参数,它将作为数组传递

test { |a| puts a.inspect }

输出

["oh", "my"]
["i", "really"]
["like", "blocks"]

所以,sayArray#each不存在,你想自己创建它。你可以做类似的事情

class Array
  def each
    i = 0
    while i < length_of_underlying_array
      next_element = get_element(i)
      yield(next_element)
    end
  end
end

或者,Hash#each

class Hash
  def each
    i = 0
    while i < length_of_underlying_hash
      next_key = keys[i]
      next_value = values[i]
      yield([next_key, next_value])
    end
  end
end

另一个通用提示,由于 Ruby 是开源的,您可以确切地看到Array#eachHash#each是如何在 C 中实现的,这通常与上面的纯 Ruby 代码相匹配。

于 2013-05-19T16:34:18.070 回答
3
  • 调用时将散列{a: => :b, :c => :d}转换为数组。[[:a, :b], [:c, :d]]each
  • 如果块 oneach接受一个 variable x,则传递它的每个元素,这是[:a, :b]第一次迭代,[:c, :d]下一次迭代。
  • 如果块 oneach接受两个变量xy,则每个元素[:a, :b]都与变量匹配。对于第一次迭代,x变得:ay变得:b
于 2013-05-19T16:28:07.927 回答