例如,要返回我可写的第10,000个素数:
require 'prime'
Prime.first(10000).last #=> 104729
但是创建一个巨大的中间数组,只是为了检索它的最后一个元素感觉有点麻烦。
鉴于Ruby是如此优雅的语言,我本来期望的是:
Prime.at(9999) #=> 104729
但没有Enumerable#at
。
上述解决方法是否有意或是否有更直接的方法来获取Enumerable
的 n 元素?
答案 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