收集和结构如何在ruby中工作?

时间:2012-10-05 06:00:17

标签: ruby

我目前正在阅读一本书,并且有一些我不太了解的代码:

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]显示,而是一次显示一个int。

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

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

3 个答案:

答案 0 :(得分:4)

  

1)现在我明白了3,2,5,8,但为什么不在数组中显示   格式[3,2,5,8]而不是一次显示一个int。

这是由于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”   在输入之前,应该不是“测试”值“测试”   值

打印值的唯一内容是对diameters的返回值的puts语句,因此在收集它们之前它们不会打印。如果你想在每次测试后打印它,你应该做类似的事情

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)另外,当我设置@wheels时,答案3,2,1,0没有任何意义   轮子不应该是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]的原因,解释了您看到的最后四位数字。

答案 1 :(得分:1)

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

2)put“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使得更容易理解的代码成为“收集”的例子。

答案 2 :(得分:0)

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

2- u未指定要显示的值。做“put wheel.rim +(wheel.tire * 2)”。

3-如果你在直径收集块方法中打印'wheel',那么

"#<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)。