Какой функциональный способ сделать это?(Вырваться из двух вложенных блоков #each) - PullRequest
1 голос
/ 24 июня 2011

Мне никогда не приходилось делать это в Ruby, но мой босс, будучи программистом на C, поставил передо мной проблему, для которой я, честно говоря, не могу предложить элегантное решение в Ruby, не делая это в основном в Cпуть (отслеживание переменной с использованием двух операторов "break").

У нас есть такая ситуация (синтаксический анализ XML):

(1..1000).each do |page|
  fetch_page(page).results.each do |results|
    do_something_with_results!
    break if results[:some_value] > another_value # this needs to exit BOTH blocks
  end
end

Единственный способ сделать это -способ, который я бы не назвал очень похожим на Ruby, а скорее на C-образное мышление.Что-то вроде:

(1..1000).each do |page|
  should_break = false
  fetch_page(page).results.each do |results|
    do_something_with_results!
    if results[:some_value] > another_value
      should_break = true
      break
    end
  end
  break if should_break
end

Мне кажется, что это неправильно и не похоже на Ruby, но каков функциональный подход?

Ответы [ 2 ]

4 голосов
/ 24 июня 2011
catch (:break) do
  (1..1000).each do |page|
    fetch_page(page).results.each do |results|
      do_something_with_results!
      throw :break if results[:some_value] > another_value # this needs to exit BOTH blocks
    end
  end
end

РЕДАКТИРОВАТЬ: @ Комментарий CaptainPete выше на месте. Если вы можете превратить его в функцию, у нее есть существенные побочные преимущества (первичное - модульное тестирование).

0 голосов
/ 24 июня 2011

Это зависит от ваших обстоятельств.

Если наборы данных не слишком велики, вы можете сделать

results = (1..1000).map{|page_number| fetch_page(page_number).results}.flatten(1)
results.each do
  do_something_with_results!
  break if results[:some_value] > another_value # this needs to exit BOTH blocks
end

в противном случае вам придется что-то сделать, чтобы сделать это более ленивым, например

def each_result(page_numbers)
  page_numbers.each do |page_number|
    fetch_page(page_number).results.each do |result|
      yield result
    end
  end
end

и я уверен, что есть много других способов сделать что-нибудь ленивым.

...