5

我必须编写一个 Ruby 方法:

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

  2. 如果没有任何数组元素符合条件,则执行 Bar 操作。

在任何其他语言中,我会在进入循环之前设置一个布尔变量,如果我做了 Foo. 该变量的值会告诉我是否需要 Bar。但这感觉非常不雅。有人可以提出更好的方法吗?

编辑一些非常好的答案,但由于我应该提到的一个细节,它们并不能很好地工作。Foo 所做的事情是对匹配条件的数组元素执行的。此外,保证最多有一个元素与条件匹配。

4

6 回答 6

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
于 2013-01-25T02:14:06.583 回答
5

你可以这样做:

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

docEnumerable#any执行以下操作:

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

于 2013-01-25T02:13:43.407 回答
5

你想要的是Enumerable#find

前任:

element = array.find { |x| x.passes_requirements? }
element ? element.foo! : bar
于 2013-01-25T03:22:22.923 回答
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

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

于 2013-01-25T02:14:51.987 回答
1
idx = the_array.index { |i| conditional(i) }
if idx
  modify_object(the_array[idx])
else
  no_matches
end
于 2013-01-25T02:39:17.383 回答
0

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

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

所以,在布尔上下文中,整个循环是true它是否完成并且false是否中断。因此

bar if array.each do |element|
  if fooable(element) then
    foo(element)
    break
  end
end
于 2013-01-31T05:10:58.590 回答