我正在尝试阅读代码以便理解。基本上这个代码应该做的是取一个名为new_str
的字符串(其数字字符总是5的倍数)并将其字符放入另一个名为new_str_2
的字符串中,以5为一组,后跟空格。例如,如果new_str
为"onetwothre"
,则new_str_2
为"onetw other"
。但我的问题是变量i
在.times
阻止中做了什么?
new_str = "thisisyetanotherstringwithoutspaces"
new_str_2 = ""
(new_str.size / 5).times { |i| new_str_2 << new_str[i * 5, 5] << " " }
new_str_2 #=> "thisi syeta nothe rstri ngwit houts paces "
答案 0 :(得分:1)
如果有一个像变量一样给出的块,那么它将从0到(new_str.size / 5) - 1
答案 1 :(得分:1)
(new_str.size / 5).times { |i| new_str_2 << new_str[i * 5, 5] << " " }
是一个枚举器,后跟一个块。枚举器是类Enumerator的一个实例,是
enum = (new_str.size / 5).times
#=> #<Enumerator: 7:times>
我们可以通过将它转换为数组来检查这个枚举器的元素:
enum.to_a
#=> [0, 1, 2, 3, 4, 5, 6]
当Ruby看到一个枚举器后跟一个块时,她将方法Enumerator#each发送给枚举器:
enum.each { |i| new_str_2 << new_str[i * 5, 5] << " " }
#=> 7
new_str_2
#=> "thisi syeta nothe rstri ngwit houts paces "
each
将enum
的每个元素传递给块,将块变量设置为等于其值。我们可以使用方法Enumerator@next来查看如何完成此操作:
i = enum.next #=> 0
i = enum.next #=> 1
i = enum.next #=> 2
...
对i
的每个值执行块计算。
现在让我们考虑第二个例子:
[[1,2], [3,4]].map { |a| a[0] + a[1] }
#=> [3,7]
enum = [[1,2], [3,4]].map
#=> #<Enumerator: [[1, 2], [3, 4]]:map>
enum.to_a
#=> [[1, 2], [3, 4]]
enum.each { |a| a[0] + a[1] }
#=> [3, 7]
a = enum.next
#=> [1, 2]
a[0] + a[1]
#=> 3
a = enum.next
#=> [3, 4]
a[0] + a[1]
#=> 7
通常你会看到这个写的
[[1,2], [3,4]].map { |a,b| a + b }
#=> [3,7]
可以说更清楚。步骤与以前一样,除了为块变量赋值时使用并行赋值(又名多重赋值):
enum = [[1,2], [3,4]].map
#=> #<Enumerator: [[1, 2], [3, 4]]:map>
a,b = enum.next
#=> [1, 2]
a #=> 1
b #=> 2
a + b
#=> 3
a,b = enum.next
#=> [3, 4]
a #=> 3
b #=> 4
a + b
#=> 7
在许多情况下,可以使用对块变量的值的并行分配。还有一个使用方法Enumerable#each_with_object:
[[1,2], [3,4]].each_with_object({}) { |(a,b),h| h[a] = b }
#=> {1=>2, 3=>4}
enum = [[1,2], [3,4]].each_with_object({})
#=> #<Enumerator: [[1, 2], [3, 4]]:each_with_object({})>
enum.to_a
#=> [[[1, 2], {}], [[3, 4], {}]]
(a,b),h = enum.next
#=> [[1, 2], {}]
a #=> 1
b #=> 2
h #=> {}
h[a] = b
#=> 2
h #=> {1=>2}
(a,b),h = enum.next
#=> [[3, 4], {1=>2}]
a #=> 3
b #=> 4
h #=> {1=>2}
h[a] = b
#=> 4
h #=> {1=>2, 3=>4}
请注意,Enumerator#each_object(Enumerator
的{{1}}对应方)可用于解决手头的问题:
Enumerable#each_with_object
答案 2 :(得分:0)
i
是从new_str_2 << new_str[i * 5, 5] << " "
获得代码(new_str.size / 5).times
的内容。
答案 3 :(得分:0)
(new_str.size / 5).times { |i| new_str_2 << new_str[i * 5, 5] << " " }
为简化操作,new_str.size / 5
评估为7
。所以你的表达式与:
7.times { |i| new_str_2 << new_str[i * 5, 5] << " " }
从i=0
到i=6
开始,您的代码块 7次。首先,我们将i=0
传递给块。然后执行以下步骤:
{ |i| new_str_2 << new_str[i * 5, 5] << " " }
{ |i=0| new_str_2 << new_str[0 * 5, 5] << " " }
{ |i=0| new_str_2 << new_str[0, 5] << " " }
{ |i=0| new_str_2 << "thisi " }
然后times
迭代器对i=1
执行相同操作,依此类推i=6
。
答案 4 :(得分:0)
在Ruby中,块声明中||
内声明的变量是“输入”参数。
鉴于,您有一个名为foo
的函数可以使用一个块,您可以按如下方式使用它:
foo(method, arguments) do
do something: funny
end
然后该块将在 foo
方法内执行,在方法想要执行它的位置;这样代码就可以轻松改变方法的行为。
在某些情况下,块可能会将一些参数传递给您。您可以在||
块中声明它们,一般来说,如果您不想使用它们,则可以声明它们。语法如下:
foo(method, arguments) do |first, second|
my_method(first)
puts second
end
因此,在times
方法的情况下,它在循环中从times
方法内部传递参数。它的内部定义可能类似于
def times count
i = 0
while i < count
yield(i)
i+=1
end
end
会导致您的块被多次调用,每次都以i
为参数。