How to get the nth element of an Enumerable in Ruby

后端 未结 4 735
甜味超标
甜味超标 2021-01-18 11:20

For example, to return the 10,000th prime number I could write:

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

But creating a huge

相关标签:
4条回答
  • 2021-01-18 11:49

    Based on sawa's solution, here's a more succinct alternative:

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

    or

    Prime.find.with_index { |_, i| i == 9999 }
    #=> 104723
    
    0 讨论(0)
  • 2021-01-18 11:50

    The closest thing I can think of to a hypothetical at method is drop, which skips the indicated number of elements. It tries to return an actual array though so you need to combine it with lazy if you are using with infinite sequences, e.g.

    Prime.lazy.drop(9999).first
    
    0 讨论(0)
  • What about this?

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

    For enumerators that are not lazy, you probably want to put lazy on the enumerator.

    0 讨论(0)
  • 2021-01-18 12:00
    module Enumerable
      def at(n)
        enum = is_a?(Enumerator) ? self : each
        (n-1).times { enum.next }
        enum.next
      end
    end
    

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

    Note that '0ab_1ab_2ab_3ab_4ab'.gsub(/.(?=ab)/).class #=> Enumerator.

    Some refinements would be needed, such as checking that n is an integer greater than zero and improving the exception handling, such as dealing with the case when self is not an enumerator but has no method each.

    0 讨论(0)
提交回复
热议问题