这样做的功能方法是什么? (打破两个嵌套的#each块)

时间:2022-12-05 14:30:13

I've never needed to do this in Ruby, but my boss, being a C programmer, has put to me a problem that I honestly can't provide an elegant solution for in Ruby, without basically doing it in the C way (tracking a variable an using two "break" statements).

我从来不需要在Ruby中这样做,但我的老板,作为一名C程序员,给我一个问题,我真的无法在Ruby中提供一个优雅的解决方案,而基本上不用C语言(跟踪)变量an使用两个“break”语句)。

We have a situation like this (parsing XML):

我们有这样的情况(解析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

The only way I could do this is in a way that I would not describe as being very Ruby-like, and more a C way of thinking. Something like:

我能做到这一点的唯一方法是,我不会将其描述为非常类似于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

That to me feels completely wrong and un-Ruby-like, but what's the functional approach?

这对我来说完全错误并且不像Ruby那样,但是什么是功能方法?

2 个解决方案

#1


4  

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

EDIT: @CaptainPete's comment above is spot on. If you can make it into a function, it has significant side benefits (unit testing being the primary one).

编辑:@上面的CaptainPete评论是现货。如果你可以把它变成一个函数,它有很大的附带好处(单元测试是主要的)。

#2


-1  

It depends on your circumstances.

这取决于你的情况。

If the data sets aren't too large, you could do

如果数据集不是太大,你可以这样做

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

otherwise you'd have to do something to make it more lazy, such as

否则你必须做一些让它更懒惰的事情,比如

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

and I'm sure there are many other ways for making something lazy.

而且我确信还有很多其他方法可以让你变得懒散。

#1


4  

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

EDIT: @CaptainPete's comment above is spot on. If you can make it into a function, it has significant side benefits (unit testing being the primary one).

编辑:@上面的CaptainPete评论是现货。如果你可以把它变成一个函数,它有很大的附带好处(单元测试是主要的)。

#2


-1  

It depends on your circumstances.

这取决于你的情况。

If the data sets aren't too large, you could do

如果数据集不是太大,你可以这样做

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

otherwise you'd have to do something to make it more lazy, such as

否则你必须做一些让它更懒惰的事情,比如

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

and I'm sure there are many other ways for making something lazy.

而且我确信还有很多其他方法可以让你变得懒散。