考虑一个包含很多元素的 Ruby 数组。
我想对数组进行反向迭代并选择给定块返回 true 的前 n 个结果。
例如
seniors = persons.reverse.select do |person|
person.age > 60
end
这没关系,但是它收集了所有前辈,而不是最多 n 个前辈。收集 n 个结果后,过早终止迭代的最佳方法是什么?
考虑一个包含很多元素的 Ruby 数组。
我想对数组进行反向迭代并选择给定块返回 true 的前 n 个结果。
例如
seniors = persons.reverse.select do |person|
person.age > 60
end
这没关系,但是它收集了所有前辈,而不是最多 n 个前辈。收集 n 个结果后,过早终止迭代的最佳方法是什么?
seniors = []
persons.reverse.each{ |p|
seniors << p if p.age > 60
break if seniors.count >= n
}
惰性求值很棒,因为它可以在不更改严格求值中通常使用的抽象的情况下编写这种代码(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
您可以链接take_while
和each_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