Sha256: 0c03da49e44865ed4b1dd25c60d67d3e43d24c5749429d84cc04399c232d0a6d

Contents?: true

Size: 1.82 KB

Versions: 35

Compression:

Stored size: 1.82 KB

Contents

#
# A Regex-queryable Hash.
#
# Usage:
#
#     greeting = Rash.new( /^Mr./ => "Hello sir!", /^Mrs./ => "Evening, madame." )
#     greeting["Mr. Steve Austin"] #=> "Hello sir!"
#     greeting["Mrs. Steve Austin"] #=> "Evening, madame."
#
class Rash
  
  attr_accessor :optimize_every
  
  def initialize(initial={})
    @hash           = {}
    @regexes        = []
    @regex_counts   = Hash.new(0)
    @optimize_every = 500
    @lookups        = 0
    
    update(initial)
  end

  def []=(key, value)
    if key.is_a? Regexp
      #key = normalize_regex(key)  # this used to just do: /#{regexp}/
      @regexes << key
    end
    @hash[key] = value
  end
  
  def search_regexes(string)
    @regexes.select { |r| string =~ r }.map { |r| @regex_counts[regex] += 1; @hash[r] } 
  end
  
  def search_strings(regex)
    keys.select { |key| key =~ regex if key.is_a? String }.map{ |key| @hash[key] }    
  end
  
  def [](key)
    return @hash[key] if @hash.include? key

    case key
      
      when String
        optimize_if_necessary!
        
        regexes = @regexes.select { |r| r =~ key }
        
        if regexes.any?
          return regexes.map do |regex|
            @regex_counts[regex] += 1 
            @hash[regex]  
          end
        end
        
      when Regexp
        
        matches = search_strings(key)
        
        if matches.any?
          return matches
        end
      
    else
      return @hash[key]
    end

    nil
  end
  
  def update(other)
    for key, value in other
      self[key] = value
    end
    self
  end
  
  def method_missing(*args, &block)
    @hash.send(*args, &block)
  end

private

  def optimize_if_necessary!
    if (@lookups += 1) >= @optimize_every    
      @regexes = @regex_counts.sort_by { |regex,count| -count }.map { |regex,count| regex }
      @lookups = 0
    end
  end

end

Version data entries

35 entries across 35 versions & 1 rubygems

Version Path
epitools-0.5.1 lib/epitools/rash.rb
epitools-0.5.0 lib/epitools/rash.rb
epitools-0.4.49 lib/epitools/rash.rb
epitools-0.4.48 lib/epitools/rash.rb
epitools-0.4.47 lib/epitools/rash.rb
epitools-0.4.46 lib/epitools/rash.rb
epitools-0.4.45 lib/epitools/rash.rb
epitools-0.4.44 lib/epitools/rash.rb
epitools-0.4.43 lib/epitools/rash.rb
epitools-0.4.42 lib/epitools/rash.rb
epitools-0.4.41 lib/epitools/rash.rb
epitools-0.4.40 lib/epitools/rash.rb
epitools-0.4.39 lib/epitools/rash.rb
epitools-0.4.38 lib/epitools/rash.rb
epitools-0.4.37 lib/epitools/rash.rb
epitools-0.4.36 lib/epitools/rash.rb
epitools-0.4.35 lib/epitools/rash.rb
epitools-0.4.34 lib/epitools/rash.rb
epitools-0.4.33 lib/epitools/rash.rb
epitools-0.4.32 lib/epitools/rash.rb