0

我目前正在阅读一本书,并且有一段我不太明白的代码:

class RevealingReferences
  attr_reader :wheels

  def initialize(data)
    @wheels = wheelify(data)
    puts data
  end

  def diameters
    wheels.collect do |wheel|
      puts "test"
      wheel.rim + (wheel.tire*2)
    end
  end

  Wheel = Struct.new(:rim, :tire)

  def wheelify(data)
    data.collect{|cell|
      Wheel.new(cell[0], cell[1])}
    end
  end
end

puts RevealingReferences.new([3,2,5,8]).diameters

我得到以下输出:

3
2
5
8
test
test
test
test
3
2
1
0

1)现在我理解了 3,2,5,8,但是为什么不以数组格式显示 [3,2,5,8] 而是一次显示一个整数。

2)另外,在wheels.collect 块中,输出在输出之前打印“test”两次,它应该不是“test”值“test”值

3)另外,答案 3,2,1,0 没有任何意义,当我设置 @wheels 时,轮子不应该是 2 个元素的数组而不是 4 个元素的集合吗?

4

3 回答 3

4

1)现在我理解了 3,2,5,8,但是为什么不以数组格式显示 [3,2,5,8] 而是一次显示一个整数。

这是由于如何puts工作。当它看到一个数组时,它会打印#to_s每个元素的

puts [1,2,3]
# >> 1
# >> 2
# >> 3

如果你想让它看起来像一个数组,你应该在打印之前检查它

puts [1,2,3].inspect
# >> [1, 2, 3]

还有一个简写,方法p

p [1,2,3]
# >> [1, 2, 3]

2)另外,在wheels.collect 块中,输出在输出之前打印“test”两次,它应该不是“test”值“test”值

打印这些值的唯一内容是关于 的返回值的 puts 语句diameters,因此它们在被收集之前不会打印。如果您想在每次测试后打印它,您可能应该执行类似的操作

def diameters
  wheels.collect do |wheel|
    puts "test"
    p wheel.rim + (wheel.tire*2)
  end
end

哪个会打印:

test
3
test
2
test
1
test
0

3)另外,答案 3,2,1,0 没有任何意义,当我设置 @wheels 时,轮子不应该是 2 个元素的数组而不是 4 个元素的集合吗?

根据您在这里所说的,我假设您的数据不是您想要的格式。您正在传递[3,2,5,8],但这意味着您要传递[[3,2],[5,8]],或映射每对值:

def wheelify(data)
  data.each_slice(2).collect do |cell|
    Wheel.new(cell[0], cell[1])
  end
end

它没有按照您的想法执行的原因是因为不执行其中之一,该cell变量实际上只是一个数字。由于数字上定义了括号方法,因此它们最终在这种情况下工作。但是括号方法只返回 1 或 0,具体取决于该位置的位(基数 2):

five = 5
five.to_s(2) # => "101"
five[2] # => 1
five[1] # => 0
five[0] # => 1

所以在 3 的情况下,wheel.rim + (wheel.tire*2)变成

cell = 3
cell.to_s(2)   # => "11"
rim = cell[0]  # => 1
tire = cell[1] # => 1
rim + tire * 2 # => 3

在 2 的情况下:

cell = 2
cell.to_s(2)   # => "10"
rim = cell[0]  # => 0
tire = cell[1] # => 1
rim + tire * 2 # => 2

和 5:

cell = 5
cell.to_s(2)   # => "101"
rim = cell[0]  # => 1
tire = cell[1] # => 0
rim + tire * 2 # => 1

和 8:

cell = 8
cell.to_s(2)   # => "1000"
rim = cell[0]  # => 0
tire = cell[1] # => 0
rim + tire * 2 # => 0

这就是为什么diameters返回[3, 2, 1, 0],解释你看到的最后四位数字。

于 2012-10-05T06:34:04.660 回答
1

1) puts 将在新行上输出每个参数,或者如果参数是数组,则在新行上输出数组的每个元素

2) puts "test" 在wheels.collect 块中运行,创建了四个Wheel 对象,因此它在创建直径数组时输出四个测试。

3) 真正的问题是在您的书中或将代码转移到您的测试环境中看起来像是拼写错误。我认为最后一行是为了阅读

puts RevealingReferences.new([[3,2],[5,8]]).diameters

否则, Wheel.new 行

 Wheel.new(cell[0], cell[1])}

正在调用 FixNum#[] 给你整数的第 n 位。这对我来说也有点意外——当意外地提供一个整数而不是一个数组时,似乎很多事情都可能出现微妙的错误。

使用原始代码,对于数据的第一个元素,cell[0] 和 cell[1] 的计算结果为 3[0] 和 3[1]。通过更正,您将拥有数组 [3,2][0] => 3 和 [3,2][1] => 2,这使得作为“收集”示例的代码更易于理解。

于 2012-10-05T06:37:07.657 回答
0

1- collect 是一个接受代码块的迭代器方法。collect 迭代器返回集合的所有元素。

2-你没有指定要显示的值。执行“放置wheel.rim + (wheel.tire*2)”。

3-如果你在直径收集块方法中打印“轮子”,它的

"#<struct RevealingReferences::Wheel rim=1, tire=1>"
"#<struct RevealingReferences::Wheel rim=0, tire=1>"
"#<struct RevealingReferences::Wheel rim=1, tire=0>"
"#<struct RevealingReferences::Wheel rim=0, tire=0>"

当执行“wheel.rim + (wheel.tire*2)”语句时,结果为 3,2,1,0 并返回每个结果。如果在直径的收集块中添加语句“放置轮子”并执行程序,您将不会在输出中看到值 (3,2,1,0)。

于 2012-10-05T06:44:21.733 回答