如何在Ruby

时间:2016-01-18 11:02:18

标签: ruby

例如,要返回我可写的第10,000个素数:

require 'prime'
Prime.first(10000).last #=> 104729

但是创建一个巨大的中间数组,只是为了检索它的最后一个元素感觉有点麻烦。

鉴于Ruby是如此优雅的语言,我本来期望的是:

Prime.at(9999) #=> 104729

但没有Enumerable#at

上述解决方法是否有意或是否有更直接的方法来获取Enumerable n 元素?

4 个答案:

答案 0 :(得分:8)

我能想到的最接近假设at方法的是drop,它会跳过指定数量的元素。它试图返回一个实际的数组,所以如果你使用无限序列,你需要将它与lazy组合,例如。

Prime.lazy.drop(9999).first

答案 1 :(得分:5)

这个怎么样?

Prime.to_enum.with_index(1){|e, i| break e if i == 10000}
# => 104729

对于非懒惰的枚举器,您可能希望将lazy放在枚举器上。

答案 2 :(得分:1)

module Enumerable
  def at(n)
    enum = is_a?(Enumerator) ? self : each
    n.times { enum.next }
    enum.next
  end
end

[0,1,2,3,4].at(3)
  #=> 3 
(0..4).at(3)
  #=> 3 
{ a:1, b:2, c:3, d:4, e:5 }.at(3)
  #=> [:d, 4] 
'0ab_1ab_2ab_3ab_4ab'.gsub(/.(?=ab)/).at(3)
  #=> "3" 
require 'prime'; Prime.at(9999)
  #=> 104729  
[0,1,2,3,4].at(5)
  #=> nil 
'0ab_1ab_2ab_3ab_4ab'.gsub(/.(?=ab)/).at(5)
  #=> StopIteration (iteration reached an end)

请注意,'0ab_1ab_2ab_3ab_4ab'.gsub(/.(?=ab)/).class #=> Enumerator

需要进行一些改进,例如检查n是自然数,并改进异常处理,例如处理self不是枚举数但没有方法{{ 1}}。

答案 3 :(得分:0)

基于sawa's solution,这里有一个更简洁的选择:

Prime.find.with_index(1) { |_, i| i == 10000 }
#=> 104729

Prime.find.with_index { |_, i| i == 9999 }
#=> 104729