Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 数组。最多选择n个元素_Ruby_Arrays_Collections - Fatal编程技术网

Ruby 数组。最多选择n个元素

Ruby 数组。最多选择n个元素,ruby,arrays,collections,Ruby,Arrays,Collections,考虑一个包含大量元素的Ruby数组 我想对数组进行反向迭代,并选择给定块返回true的前n个结果 例如 这是可以的,但是它收集所有的前辈,而不是最多n个前辈。当收集到n个结果时,提前终止迭代的最佳方法是什么?您可以将take\u while和每个\u链接到\u对象: seniors = [] persons.reverse.each{ |p| seniors << p if p.age > 60 break if seniors.count >= n } 它非

考虑一个包含大量元素的Ruby数组

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

例如

这是可以的,但是它收集所有的前辈,而不是最多n个前辈。当收集到n个结果时,提前终止迭代的最佳方法是什么?

您可以将take\u while和每个\u链接到\u对象:

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:

是seniors=seniors.firstn选项,而不是过早终止?您可以直接调用。在end@user2864740那不是真的。对于数组[1,2,3,61],take3将排除应包含在结果中的61set@user2864740,您的示例将n个元素切片,然后从中进行选择,对吗?那不是我想要做的。我最多只想选择n个元素,而不是从n个元素中选择。我不认为相反的方法实际上也能做任何事情,但这取决于输入数组是什么。这将完成它。如果seniors数组非常大,我也可以在单独的count变量中跟踪其大小,而不是在每次迭代中调用.count。不完全确定,但据我所知,数组数据类型已经跟踪其计数本身了。@NielsB。除了性能,还有更多的考虑因素。必须更新代码的人可能会被无用的代码弄糊涂reverse@NielsB.,而不是反转然后迭代,您也可以使用
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
# Ruby >= 2.0
seniors = persons.reverse.lazy.select { |person| person.age > 60 }.take(n)