Ruby 语法:从 'each.. do..' 块中跳出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8502397/
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-03 02:29:32  来源:igfitidea点击:

Ruby syntax: break out from 'each.. do..' block

ruby-on-railsrubyruby-on-rails-3ruby-on-rails-3.1

提问by Mellon

I am developing a Ruby on Railsapp. My question is more about Rubysyntax.

我正在开发一个Ruby on Rails应用程序。我的问题更多是关于Ruby语法的。

I have a model class with a class method self.check:

我有一个带有类方法的模型类self.check

class Cars < ActiveRecord::Base
  ...
  def self.check(name)
     self.all.each do |car|
          #if result is true, break out from the each block, and return the car how to...
          result = SOME_CONDITION_MEET?(car) #not related with database
     end

     puts "outside the each block."
  end
end

I would like to stop/break out from the eachblock oncethe resultis true(that's break the eachblock if car.nameis the same as the nameparameter once) AND return the carwhich cause the trueresult. How to break out in Ruby code?

我想停止/从跳出each一次result真实的(这是打破eachif块car.name是一样的name参数一次),并返回car其导致真正的结果。如何在 Ruby 代码中突围?

回答by tbuehlmann

You can break with the breakkeyword. For example

您可以使用break关键字中断。例如

[1,2,3].each do |i|
  puts i
  break
end

will output 1. Or if you want to directly return the value, use return.

将输出1. 或者,如果您想直接返回值,请使用return.

Since you updated the question, here the code:

由于您更新了问题,因此代码如下:

class Car < ActiveRecord::Base
  # …

  def self.check(name)
    self.all.each do |car|
      return car if some_condition_met?(car)
    end

    puts "outside the each block."
  end
end

Though you can also use Array#detector Array#any?for that purpose.

虽然您也可以使用Array#detectArray#any?用于该目的。

回答by tokland

I provide a bad sample code. I am not directly find or check something from database. I just need a way to break out from the "each" block if some condition meets once and return that 'car' which cause the true result.

我提供了一个糟糕的示例代码。我不是直接从数据库中查找或检查某些内容。如果某些条件满足一次并返回导致真实结果的“汽车”,我只需要一种方法来从“每个”块中跳出。

Then what you need is:

那么你需要的是:

def check(cars, car_name)
  cars.detect { |car| car.name == car_name }
end

If you wanted just to know if there was any car with that name then you'd use Enumerable#any?. As a rule of thumb, use Enumerable#eachonly to do side effects, not perform logic.

如果您只想知道是否有任何具有该名称的汽车,那么您可以使用Enumerable#any?. 根据经验,Enumerable#each仅用于产生副作用,而不是执行逻辑。

回答by Sayuj

you can use include?method.

你可以使用include?方法。

def self.check(name)
  cars.include? name
end

include?returns trueif nameis present in the carsarray else it returns false.

include?返回true如果name是存在于在cars阵列否则它返回false

回答by davidb

You can use breakbut what your are trying to do could be done much easier, like this:

您可以使用break但您尝试做的事情可以更容易地完成,如下所示:

def self.check(name)
  return false if self.find_by_name(name).nil?
  return true
end

This uses the database. You are trying to use Ruby at a place the database can deal with it better.

这将使用数据库。您正在尝试在数据库可以更好地处理它的地方使用 Ruby。

You can also use breakconditional:

您还可以使用break条件:

break if (car.name == name)

回答by user208769

I had to do this exact same thing and I was drawing a blank. So despite this being a very old question, here's my answer:

我不得不做完全相同的事情,我正在画一个空白。因此,尽管这是一个非常古老的问题,但这是我的答案:

Note: This answer assumes you don't want to return the item as it exists within the array, but instead do some processing on the item and return the result of that instead.That's how I originally read the question, I realise now that was incorrect - though this approach can be easily modified for that effect (break iteminsead of break output)

注意:此答案假设您不想返回数组中存在的项目,而是对该项目进行一些处理并返回结果。这就是我最初阅读问题的方式,我现在意识到这是不正确的 - 尽管可以轻松修改此方法以实现该效果(break iteminsead of break output

Since returning from blocks is dodgy (nobody likes it, and I think the rules are about to change which makes it even more fraught) this is a much nicer option:

由于从块中返回是狡猾的(没有人喜欢它,而且我认为规则即将改变,这使得它更加令人担忧)这是一个更好的选择:

collection.inject(nil) do |_acc, item|
  output = expensive_operation(item)
  break output if output
end

Note that there are lots of variants; for example, if you don't want an incidental variable, and don't mind starting a second loop in some circumstances, you can invert it like this:

请注意,有很多变体;例如,如果您不想要一个附带变量,并且在某些情况下不介意开始第二个循环,您可以像这样反转它:

collection.inject(nil) do |acc, item|
  break acc if acc
  expensive_operation(item)
end