Prodigy_Internet
Prodigy_Internet

Reputation: 45

Is there way to assign and break within the block?

I know I can write it this way successfully:

def test_find_first_multiple_of_3
  numbers = [2, 8, 9, 27, 24, 5]
  found = nil
  numbers.each do |number|
    if number % 3 == 0
      found = number
      break
    end
  end
  assert_equal 9, found
end

Is there anyway to do within the block? What am I missing? Or is just not possible?

numbers.each { |n| n % 3 == 0 ? (found = n then break) : nil }

def test_find_first_multiple_of_3
  numbers = [2, 8, 9, 27, 24, 5]
  found = nil
  numbers.each { |n| n % 3 == 0 ? (found = n then break) : nil }
  assert_equal 9, found
end

Upvotes: 2

Views: 108

Answers (4)

luiscrjr
luiscrjr

Reputation: 7258

As pointed by other answers, there are other ruby ways to accomplish your algorithm goal, like using the .find method:

found = numbers.find { |n| (n % 3).zero? }

This way, you don't need to break your loop.

But, specifically answering your question, there are some ways to break the loop in the same line, if you want so:

  • use ; (multiple statements separator):

    numbers.each { |n| n % 3 == 0 ? (found = n; break) : nil }
    
  • or put your assigment after break, that works too:

    numbers.each { |n| n % 3 == 0 ? (break found = n) : nil }
    

I just used your code in the example, but, again, that's not a good pratice, because, as well pointed by @the Tin Man, "hurts readability and maintenance".

Also, as pointed by @akuhn, you don't need to use ternary here. You can simply use:

numbers.each { |n| break found = n if n % 3 == 0 }

** EDITED to include suggestions from @the Tin Man, @akuhn and @Eric Duminil, in order to warn OP that there are other alternatives to run his task, that doesn't need to break loop. The original answer was written just to answer OP's question specifically (one line break loop), without the code structure concern.

Upvotes: 4

akuhn
akuhn

Reputation: 27793

Yes, both break and next take an argument.

For your example though, best use find

 founds = numbers.find { |n| n % 3 == 0 }

Generally in Ruby there is rarely a reason to break out of a loop.

You can typically use find or any of the other functions provided by the Enumerable module, like take_while and drop_while

Upvotes: 1

user9903
user9903

Reputation:

You can use the enumerable method find to find the first item that matches. Usually you will want to use enumerable methods like cycle, detect, each, reject, and others to make the code more compact while remaining understandable:

def test_find_first_multiple_of_3
  numbers = [2, 8, 9, 27, 24, 5]
  found = numbers.find { |number| number % 3 == 0 }
  assert_equal 9, found
end

Upvotes: 0

spickermann
spickermann

Reputation: 106802

With common Ruby idioms your can write:

def test_find_first_multiple_of_3
  numbers = [2, 8, 9, 27, 24, 5]
  found = numbers.find { |n| (n % 3).zero? }

  assert_equal 9, found
end

Upvotes: 1

Related Questions