何时以及为何在 Ruby 中使用 Loop Do Construct

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16813199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 06:00:20  来源:igfitidea点击:

When and Why use Loop Do Construct in Ruby

rubyloopslanguage-construct

提问by JaTo

I recently came up across a problem/solution that used Loop Do. I seldom have seen this so far in my learning Ruby Programming (I am a beginner with no CS experience).

我最近遇到了一个使用 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

SOLUTION

解决方案

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)

Can someone please explain to me when is the best time to use a "loop do" construct instead of the usual "while" or "unless" or "each" construct?

有人可以向我解释什么时候是使用“loop do”构造而不是通常的“while”或“unless”或“each”构造的最佳时间?

回答by radyz

Adding up to the previous answers,

加上之前的答案,

The "loop do" construct also offers a cleaner syntax when working with external iterators, e.g

在使用外部迭代器时,“loop do”构造还提供了更清晰的语法,例如

No "loop do"

没有“循环做”

my_iterator = (1..9).each
begin
  while(true)
    puts my_iterator.next
  end
rescue StopIteration => e
  puts e
end

And now with "loop do" this would become

现在有了“循环做”这将变成

my_iterator = (1..9).each
loop do
  puts my_iterator.next
end

And the exception is handled for you. It also allows you to loop through two collections at the same time and as soon as one of them runs out of elements the loop exits gracefully,

并且为您处理异常。它还允许您同时循环遍历两个集合,一旦其中一个集合用完元素,循环就会优雅地退出,

iterator = (1..9).each
iterator_two = (1..5).each

loop do
  puts iterator.next
  puts iterator_two.next
end

It will print: 1,1,2,2,3,3,4,4,5,5,6.

它将打印:1,1,2,2,3,3,4,4,5,5,6。

More info on it at: ruby-docs.org

有关更多信息,请访问:ruby-docs.org

回答by Neil Slater

In a language without loop, you might use a whileconstruct like:

在没有 的语言中loop,您可能会使用如下while结构:

while( true ) {
  # Do stuff until you detect it is done
  if (done) break;
}

The point of it is that you start the loop without knowing how many of iterations to perform (or it is hard to calculate in advance), but it is easy to detect when the loop should end. In addition, for a particular case you might find the equivalent while (! done) { # do stuff }syntax clumsy, because the done condition can happen halfway through the loop, or in multiple places.

关键是您在不知道要执行多少次迭代的情况下开始循环(或者很难提前计算),但是很容易检测到循环何时结束。此外,对于特定情况,您可能会发现等效while (! done) { # do stuff }语法很笨拙,因为 done 条件可能发生在循环的中途,或发生在多个地方。

Ruby's loopis basically the same thing as the while( true )- in fact you can use while( true )almost interchangeably with it.

Ruby 与 Rubyloop基本上是一样的while( true )——事实上,你while( true )几乎可以与它互换使用。

In the given example, there are following points of return within each iteration:

在给定的示例中,每次迭代中有以下返回点:

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 

There is also an implied "else continue looping" here, if no end conditions are met.

如果没有满足结束条件,这里还有一个隐含的“其他继续循环”。

These multiple possible exit points are presumably why the author chose the loopconstruct, although there are many ways of solving this problem in practice with Ruby. The given solution code is not necessarily superior to all other possibilities.

这些多个可能的退出点大概是作者选择该loop构造的原因,尽管在实践中使用 Ruby 有很多方法可以解决这个问题。给定的解决方案代码不一定优于所有其他可能性。

回答by Woot4Moo

Using the loop doconstruct allows you to break on a conditional.

使用loop do构造允许您在条件下中断。

for instance:

例如:

i=0
loop do
  i+=1
  print "#{i} "
  break if i==10
end 

You would want to use this when you know the number of elements that will be processed, similar to that of the for eachloop

当您知道将被处理的元素数量时,您会想要使用它,类似于for each循环的数量

回答by Sachin Singh

loop with 'loop' construct will execute the given block endlessly until the code inside the block breaks on certain condition.

带有 'loop' 结构的循环将无休止地执行给定的块,直到块内的代码在特定条件下中断。

it can be used when you don't have a collection to loop over, the places where 'each' and 'for' cannot work.

当您没有要循环的集合时,可以使用它,“each”和“for”不能工作的地方。

the different between 'loop' and while/until is that while/until will execute the given block when certain condition is meet, where as in case of loop there is no condition to start, condition lies inside the loop's block.

'loop' 和 while/until 之间的区别在于,while/until 将在满足特定条件时执行给定的块,在循环没有条件启动的情况下,条件位于循环块内。

for better understanding read doc.

为了更好地理解阅读文档。

http://www.ruby-doc.org/core-1.9.2/Kernel.html#method-i-loop

http://www.ruby-doc.org/core-1.9.2/Kernel.html#method-i-loop

回答by Sapphire_Brick

Suppose You wanted to put a number of conditions, it might be neater to put them together. Instead of this, for example:

假设您想放置多个条件,将它们放在一起可能会更简洁。取而代之的是,例如:

x = 0
while x <= 10
    num = gets.to_f

    break if num < 1
    break if /\D/.match? num.to_s

    puts num ** 2
end

Grouping the breaks together makes it more readable

将中断分组在一起使其更具可读性

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