2

考虑一个包含很多元素的 Ruby 数组。

我想对数组进行反向迭代并选择给定块返回 true 的前 n 个结果。

例如

seniors = persons.reverse.select do |person|
  person.age > 60
end

这没关系,但是它收集了所有前辈,而不是最多 n 个前辈。收集 n 个结果后,过早终止迭代的最佳方法是什么?

4

3 回答 3

3
seniors = []
persons.reverse.each{ |p| 
  seniors << p if p.age > 60
  break if seniors.count >= n
}
于 2013-11-06T22:21:00.710 回答
2

惰性求值很棒,因为它可以在不更改严格求值中通常使用的抽象的情况下编写这种代码(Haskell 已经证明了它的强大功能)。幸运的是,Ruby 2.0 将在这方面提供一些基础设施,届时您将能够编写以下代码:

# Ruby >= 2.0
seniors = persons.reverse.lazy.select { |person| person.age > 60 }.take(n)

对于 Ruby < 2.0:https ://github.com/yhara/enumerable-lazy

于 2013-11-06T23:46:33.603 回答
1

您可以链接take_whileeach_with_object

seniors = []
persons.take_while.each_with_object(seniors) do |e, o| 
  o << e if e.age > 60 && o.count < 1000
  o.count < 1000
end

require 'ostruct'
require 'benchmark'

persons = 1000000.times.map {|i| OpenStruct.new age: Random.rand(50..85) }

Benchmark.bm do |b|
  b.report do
    seniors = []
    persons.take_while.each_with_object(seniors) do |e, o| 
      o << e if e.age > 60 && o.count < 1000
      o.count < 1000
    end
  end
end

#=> finishes in 1-3ms on my machine
于 2013-11-06T22:59:46.387 回答