class MergeEnum::MergeEnumerable

Public Class Methods

new(*args) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 7
def initialize *args
  if args.last.is_a? Hash
    @options = args.delete_at -1
    @collections = args
  else
    @options = {}
    @collections = args
  end
end

Public Instance Methods

concat(arg) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 195
def concat arg
  self.class.new *@collections, arg, @options
end
concat!(arg) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 199
def concat! arg
  @collections.push arg
  self
end
each(&block) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 17
def each &block
  return self.to_enum unless block_given?

  opt_cache = @options[:cache]
  if opt_cache
    if @cache
      @cache.each &block
      return self
    end
  elsif @cache
    @cache = nil
  end

  # options
  opt_fst = option_first @options
  (opt_proc, _proc) = merge_options_proc @options
  (opt_map, _map) = map_proc @options
  opt_fill = @options[:fill]

  # local variables
  cnt = 0
  fst = nil
  cache = [] if opt_cache

  cs = if opt_fst and opt_fill
         @collections + [opt_fill]
       else
         @collections
       end
  cs.each do |c|
    if opt_fst
      fst = opt_fst - cnt
      break if fst <= 0
    end

    # get enumerable
    called_first = false
    if c.is_a? Proc
      arity = c.arity.abs
      case arity
      when 0
        c = c.call
      when 1
        c = c.call fst
        called_first = true
      when 2
        c = c.call fst, opt_proc
        called_first = true
      else
        args = Array.new arity - 2, nil
        c = c.call fst, opt_proc, *args
        called_first = true
      end
    end

    if fst
      # with first option
      c = c.first fst unless called_first or _proc
      _cnt = 0
      c.each do |e|
        next if _proc and not opt_proc.call e, cnt
        e = opt_map.call e, cnt if _map
        block.call e
        cache.push e if cache
        cnt += 1
        _cnt += 1
        break if fst <= _cnt
      end
    else
      # without first option
      c.each do |e|
        next if _proc and not opt_proc.call e, cnt
        e = opt_map.call e, cnt if _map
        block.call e
        cache.push e if cache
        cnt += 1
      end
    end
  end

  @cache = cache if cache

  self
end
merge_options(opts) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 204
def merge_options opts
  raise "opts must be a Hash" if opts and not opts.is_a? Hash
  self.class.new *@collections, (@options.merge opts || {})
end
Also aliased as: options
merge_options!(opts) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 209
def merge_options! opts
  raise "opts must be a Hash" if opts and not opts.is_a? Hash
  @options.merge! opts || {}
  self
end
Also aliased as: options!
options(opts)
Alias for: merge_options
options!(opts)
Alias for: merge_options!
replace_options(opts) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 215
def replace_options opts
  raise "opts must be a Hash" if opts and not opts.is_a? Hash
  self.class.new *@collections, opts || {}
end
replace_options!(opts) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 220
def replace_options! opts
  raise "opts must be a Hash" if opts and not opts.is_a? Hash
  @options = opts || {}
  self
end

Private Instance Methods

map_proc(options) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 170
def map_proc options
  opt_map = options[:map]
  if opt_map
    unless opt_map.is_a? Proc
      raise ":map is must be a Proc"
    end
    arity = opt_map.arity.abs
    case arity
    when 0
      [-> (e, i) { opt_map.call }, true]
    when 1
      [-> (e, i) { opt_map.call e }, true]
    when 2
      [opt_map, true]
    else
      args = Array.new arity - 2, nil
      [-> (e, i) { opt_map.call e, i, *args }, true]
    end
  else
    [-> (e, i) { e }, false]
  end
end
merge_options_proc(options) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 121
def merge_options_proc options
  opts = []

  opt_cmpct = options[:compact]
  opts << if opt_cmpct.is_a? Proc
            arity = opt_cmpct.arity.abs
            case arity
            when 0
              [-> (e, i) { not opt_cmpct.call }, true]
            when 1
              [-> (e, i) { not opt_cmpct.call e }, true]
            when 2
              [-> (e, i) { not opt_cmpct.call e, i }, true]
            else
              args = Array.new arity - 2, nil
              [-> (e, i) { not opt_cmpct.call e, i, *args }, true]
            end
          elsif opt_cmpct
            [-> (e, i) { not e.nil? }, true]
          else
            [-> (e, i) { true }, false]
          end

  opt_slct = options[:select]
  opts << if opt_slct.is_a? Proc
            arity = opt_slct.arity.abs
            case arity
            when 0
              [-> (e, i) { opt_slct.call }, true]
            when 1
              [-> (e, i) { opt_slct.call e }, true]
            when 2
              [-> (e, i) { opt_slct.call e, i }, true]
            else
              args = Array.new arity - 2, nil
              [-> (e, i) { opt_slct.call e, i, *args }, true]
            end
          elsif opt_slct
            raise ":select is must be a Proc"
          else
            [-> (e, i) { true }, false]
          end

  [
    -> (e, i) { opts.all?{ |opt| opt[0].call e, i } },
    opts.any?{ |opt| opt[1] }
  ]
end
option_first(options) click to toggle source
# File lib/merge_enum/merge_enumerable.rb, line 104
def option_first options
  opt_fst = options[:first]
  if opt_fst
    if opt_fst.is_a? Proc
      arity = opt_fst.arity.abs
      case arity
      when 0
        opt_fst = opt_fst.call
      else
        opt_fst = opt_fst.call *Array.new(arity, nil)
      end
    end
    opt_fst = opt_fst.to_i
  end
  opt_fst
end