优雅的循环Elsing在Ruby中

时间:2013-01-25 02:09:26

标签: ruby loops

我必须编写一个Ruby方法:

  1. 遍历数组,如果其中一个元素符合某个条件,则执行Foo。

  2. 如果没有数组元素符合条件,请执行Bar thing。

  3. 在任何其他语言中,我在进入循环之前设置一个布尔变量,如果我做了Foo,则切换它。该变量的值将告诉我是否需要Bar。但这感觉非常不优雅。任何人都能提出更好的建议吗?

    编辑一些非常好的答案,但由于我应该提到的细节,它们不太有用。 Foo所做的事情是对匹配条件的数组元素完成的。此外,它保证最多只有一个元素符合条件。

6 个答案:

答案 0 :(得分:6)

是否有任何项目匹配?如果是,那么做一些事情,不涉及匹配的项目。

if items.any? { |item| item.totally_awesome? }
  foo "we're totally awesome!"
else
  bar "not awesome :("
end

抓住第一个匹配的项目。如果存在,则使用匹配项执行某些操作。

awesome_item = items.find { |item| item.totally_awesome? }
if awesome_item
  foo "#{awesome_item.name} is totally awesome!"
else
  bar "no items are awesome :("
end

抓取所有匹配的商品。如果数组中有任何内容,则对所有匹配项执行某些操作。

awesome_items = items.find_all { |item| item.totally_awesome? }
if awesome_items.any?
  foo "#{awesome_items.size} totally awesome items!"
else
  bar "no items are awesome :("
end

答案 1 :(得分:5)

你可以这样做:

if array.any? { |elem| elem.condition }
  foo
else
  bar
end

docEnumerable#any执行以下操作:

  

将集合的每个元素传递给给定的块。如果块返回的值不是false或nil,则该方法返回true。

答案 2 :(得分:5)

你想要的是Enumerable#find

例如:

element = array.find { |x| x.passes_requirements? }
element ? element.foo! : bar

答案 3 :(得分:1)

编辑:根据新的问题标准修改。

found_index = nil
my_array.each_with_index.detect { |elem, i| elem.condition? && found_index = i }
if found_index.nil?
  do_not_found_case
else
  my_array[found_index] = some_conversion(elem)
end

这不是很漂亮,但它完成了工作,并且在第一场比赛中仍然短路。

答案 4 :(得分:1)

idx = the_array.index { |i| conditional(i) }
if idx
  modify_object(the_array[idx])
else
  no_matches
end

答案 5 :(得分:0)

感谢所有试图回答这个问题的人。你们没有提供我认为合适的答案,但是你们都强迫我思考你们如何用Ruby的方式做事(这是本练习的主要内容!)并帮助我提出了这个答案:

我需要利用Ruby中的迭代器只是方法这一事实。所有方法都返回一个值,(奇怪的是)each返回有用的值。如果迭代完成,它将返回您正在迭代的集合;如果您使用break提前终止迭代,则返回nil(或可选参数)。

因此,在布尔上下文中,整个循环如果完成则为true,如果突破则为false。因此

bar if array.each do |element|
  if fooable(element) then
    foo(element)
    break
  end
end