考虑一个带有大量元素的的Ruby数组。
我希望对数组进行反向迭代,并选择给定块返回true的前n个结果。
例如。
seniors = persons.reverse.select do |person|
person.age > 60
end这是可以的,但是它收集了所有的老年人,而不是最多的n名老年人。当收集到n个结果时,提前终止迭代的最好方法是什么?
发布于 2013-11-06 22:21:00
seniors = []
persons.reverse.each{ |p|
seniors << p if p.age > 60
break if seniors.count >= n
}发布于 2013-11-06 23:46:33
懒惰评价很棒,因为它可以在不改变通常用于严格计算的抽象的情况下编写这类代码(Haskell已经证明了这是多么强大)。幸运的是,Ruby2.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-06 22:59:46
您可以连锁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 machinehttps://stackoverflow.com/questions/19823896
复制相似问题