我最近遇到了使用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,3],2).should == 1 end it "treats any two larger numbers like a tie" do nearest_larger([2,6,2).should == 1 end it "should choose the left case in a tie" do nearest_larger([2,6],2).should == 1 end it "handles a case with an answer > 1 distance to the left" do nearest_larger([8,2,2).should == 0 end it "handles a case with an answer > 1 distance to the right" do nearest_larger([2,1).should == 3 end it "should return nil if no larger number is found" do nearest_larger( [2,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,1)
有人可以向我解释何时是使用“循环做”构造而不是通常的“while”或“除非”或“每个”构造的最佳时间?
解决方法
在没有循环的语言中,您可以使用while构造,如:
while( true ) { # Do stuff until you detect it is done if (done) break; }
关键是你在不知道要执行多少次迭代的情况下启动循环(或者很难提前计算),但是很容易检测循环何时结束.另外,对于特定情况,您可能会发现等效的while(!done){#do stuff}语法笨拙,因为完成条件可能发生在循环的中途,或者在多个地方.
Ruby的循环与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
如果没有满足结束条件,这里还有一个暗示的“其他继续循环”.
这些多个可能的出口点可能是作者选择循环结构的原因,尽管在实践中使用Ruby有很多方法可以解决这个问题.给定的解决方案代码不一定优于所有其他可能性.