sawa
sawa

Reputation: 168101

A hash-like object that acts like a case statement

What is the best way to construct a hash-like class Case, which is initialized by a hash:

cs = Case.new(:a => 1, /b/ => 2, /c/ => 2, /d/ => 3)

and has a method Case#[] that looks up for the first matching key by === (like a case statement) instead of by == (like the conventional hash) and returns the value:

cs["xxb"] => 2

Upvotes: 0

Views: 138

Answers (1)

Cary Swoveland
Cary Swoveland

Reputation: 110685

Here's a possibility.

class Case
  def initialize(h)
    @h = h
  end
  def [](key,order=:PRE)
    case order
    when :PRE 
      h[@h.keys.find { |k| key === k }]
    when :POST
      h[@h.keys.find { |k| k === key }]
    else
      # raise exception
    end
  end
end

cs = Case.new(:a => 1, /b/ => 2, /c/ => 2, [1,2] => "cat", /d/ => 3)

cs["xxb"]        #=> nil
cs["xxb",:POST]  #=> 2
cs[Regexp]       #=> 2
cs[Regexp,:POST] #=> nil
cs[Array]        #=> "cat"
cs[Symbol]       #=> 1

This assumes h does not have a key nil.


With the understanding that the key in the hash is to come on the left side of ===, the code would be:

class Case
  def initialize(h) @h = h end
  def [](key) h[@h.keys.find{|k| k === key}] end
end

Upvotes: 2

Related Questions