我最近遇到了一个使用Loop Do的问题/解决方案。到目前为止,我在学习Ruby编程时很少看到这种情况(我是一个没有CS经验的初学者)。
# Write a function, `nearest_larger(arr, i)` which takes an array and an
# index. The function should return another index, `j`: this should
# satisfy:
#
# (a) `arr[i] < arr[j]`, AND
# (b) there is no `j2` closer to `i` than `j` where `arr[i] < arr[j]`.
#
# In case of ties (see example beow), choose the earliest (left-most)
# of the two indices. If no number in `arr` is largr than `arr[i]`,
# return `nil`.
#
# Difficulty: 2/5
describe "#nearest_larger" do
it "handles a simple case to the right" do
nearest_larger([2,3,4,8], 2).should == 3
end
it "handles a simple case to the left" do
nearest_larger([2,8,4,3], 2).should == 1
end
it "treats any two larger numbers like a tie" do
nearest_larger([2,6,4,8], 2).should == 1
end
it "should choose the left case in a tie" do
nearest_larger([2,6,4,6], 2).should == 1
end
it "handles a case with an answer > 1 distance to the left" do
nearest_larger([8,2,4,3], 2).should == 0
end
it "handles a case with an answer > 1 distance to the right" do
nearest_larger([2,4,3,8], 1).should == 3
end
it "should return nil if no larger number is found" do
nearest_larger( [2, 6, 4, 8], 3).should == nil
end
end
解决方案def nearest_larger(arr, idx)
diff = 1
loop do
left = idx - diff
right = idx + diff
if (left >= 0) && (arr[left] > arr[idx])
return left
elsif (right < arr.length) && (arr[right] > arr[idx])
return right
elsif (left < 0) && (right >= arr.length)
return nil
end
diff += 1
end
end
nearest_larger([2,4,3,8], 1)
谁能给我解释一下什么时候是使用"循环做"结构而不是通常的"while"或"unless"或"each"结构的最佳时间?
把前面的答案加起来,
"loop do"结构在使用外部迭代器时也提供了更清晰的语法,例如
没有"loop do"
my_iterator = (1..9).each
begin
while(true)
puts my_iterator.next
end
rescue StopIteration => e
puts e
end
现在加上"loop do"这就变成了
my_iterator = (1..9).each
loop do
puts my_iterator.next
end
为您处理异常。它还允许您同时遍历两个集合,一旦其中一个集合的元素耗尽,循环就会优雅地退出,
iterator = (1..9).each
iterator_two = (1..5).each
loop do
puts iterator.next
puts iterator_two.next
end
它将打印:1,1,2,2,3,3,4,4,5,5,6。
更多信息请访问:ruby-docs.org
在没有loop
的语言中,您可以使用while
结构,如:
while( true ) {
# Do stuff until you detect it is done
if (done) break;
}
它的要点是,您开始循环时不知道要执行多少次迭代(或者很难提前计算),但是很容易检测到循环何时应该结束。此外,对于特定情况,您可能会发现等效的while (! done) { # do stuff }
语法很笨拙,因为done条件可能发生在循环的中途,或者在多个地方。
Ruby的loop
和while( true )
基本上是一样的——实际上你几乎可以把while( true )
和它互换使用。
在给定的示例中,在每次迭代中有以下返回点:
if (left >= 0) && (arr[left] > arr[idx])
return left # <-- HERE
elsif (right < arr.length) && (arr[right] > arr[idx])
return right # <-- HERE
elsif (left < 0) && (right >= arr.length)
return nil # <-- HERE
end
如果不满足结束条件,这里还有一个隐含的"else continue loops "。
这些可能的退出点大概是作者选择loop
结构的原因,尽管在Ruby实践中有许多方法可以解决这个问题。给定的解决方案代码不一定优于所有其他可能性。
使用loop do
结构允许您在条件上中断。
例如:
i=0
loop do
i+=1
print "#{i} "
break if i==10
end
当你知道要处理的元素数量时,你会想要使用这个,类似于for each
循环
带有'loop'结构的循环将无限地执行给定的块直到块内的代码在特定条件下中断。
可以在没有要循环的集合时使用"each"one_answers"for"不能工作的地方。
'loop'和while/until之间的区别在于while/until将当满足某些条件时执行给定的块,其中如如果循环没有条件启动,条件就在里面循环障碍。
为了更好地理解,请阅读doc.
http://www.ruby-doc.org/core-1.9.2/Kernel.html method-i-loop
假设您想要放置多个条件,将它们放在一起可能会更简洁。而不是这样,例如:
x = 0
while x <= 10
num = gets.to_f
break if num < 1
break if /D/.match? num.to_s
puts num ** 2
end
将换行符组合在一起使其更具可读性
x = 0
loop do
num = gets.to_f
break if num < 1
break if x <= 10
break if /D/.match? num.to_s
puts num ** 2
end