Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant Loop Elsing in Ruby

Tags:

loops

ruby

I have to write a Ruby method that:

  1. Iterates through an array, doing Foo if one of the elements matches a certain condition.

  2. If none of the array elements matched the condition, do Bar thing.

In any other language, I'd set a Boolean variable before entering the loop and toggle it if I did Foo. The value of that variable would tell me whether I needed to Bar. But that feels unRubyishly inelegant. Can anybody suggest a better way?

Edit Some really good answers, but they don't quite work because of a detail I should have mentioned. The something that Foo does is done to the array element that matches the condition. Also, it's guaranteed that at most one element will match the condition.

like image 708
Isaac Rabinovitch Avatar asked Jan 25 '13 02:01

Isaac Rabinovitch


2 Answers

Do any of the items match? If yes, then do something, not involving the matching item.

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

Grab the first matching item. If it exists, then do something, with the matching item.

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

Grab all matching items. If the array has anything in it, then do something with all matching items.

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
like image 54
Alex Wayne Avatar answered Nov 16 '22 04:11

Alex Wayne


You could do it like this:

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

From the doc, Enumerable#any does the following:

Passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil.

like image 5
user2398029 Avatar answered Nov 16 '22 04:11

user2398029