Home > OS >  Ruby: How to create a custom iteration method for a Enumerator Object - with enum_for?
Ruby: How to create a custom iteration method for a Enumerator Object - with enum_for?

Time:12-11

Lets say, we have an Array of Strings named words and I want to instantiate a special Enumerator using eunum_for on it which only counts Strings with the length != 3. Here is my proposal:

def words.n_each
  select{|x| x.length != 3}.each do |y|
    yield y
  end
end

e4 = words.enum_for(:n_each)
e4.each do |w|
  puts w
end

But there has to be a more smarter rubyish way to include the mechanics of the n_each method in enum_for - maybe inside a codeblock at the time of instantiation of the Enumerator. But how?

CodePudding user response:

Is lazy what you are looking for?

p e4 = ["aaa","c","foo","aaaa"].lazy.reject{|s| s.size == 3 } # => <Enumerator::Lazy: ["aaa", "c", "foo", "aaaa"]>:reject>

e4.each do |w|
  puts w
end

prints

c
aaaa

CodePudding user response:

class Array
  def each_except_size_3
    Enumerator.new do |y|
      (0..size-1).each do |i|
        s = self[i]
        y << s unless s.size == 3
      end
    end
  end
end
enum = ['guppy', 'owl', 'ox', 'cow', 'bear', 'lion'].each_except_size_3
  #=> #<Enumerator: #<Enumerator::Generator:0x00007fc1a41b9a28>:each>
enum.to_a
  #=> ["guppy", "ox", "bear", "lion"]
enum.take(4)
  #=> ["guppy", "ox", "bear", "lion"]
enum.take(3)
  #=> ["guppy", "ox", "bear"]
enum.take(99)
  #=> ["guppy", "ox", "bear", "lion"]
enum.next
  #=> "guppy"
enum.next
  #=> "ox"
enum.next
  #=> "bear"
enum.next
  #=> "lion"
enum.next
  #=> StopIteration: iteration reached an end
  • Related