From: Josh Cheek Date: 2011-04-17T01:17:36+09:00 Subject: Re: Get the real object in a Hash key --0016e64cb1ead1d3cf04a10b7db9 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On Sat, Apr 16, 2011 at 9:51 AM, I=F1aki Baz Castillo wrote= : > 2011/4/15 Kevin Mahler : > > He has a key. It contains some > > data. It's not necessarily true that he should duplicate that data in > > the mapped-to values. > > To clarify, my exact case is the following: > > I've coded a parser for SIP (similar to HTTP). The parser generates a > Request object which inherits from Hash, and each SIP request header > (i.e. "From: sip:alice@example.org") becomes an entry of the hash > (Request object) as follows: > > - The key is "FROM" (capitalized). > - The value is an Array of strings (a s header can have multiple values). > > I need to store the key capitalized for fastest lookup, but I also > want to store the original header name (which could be "from", "From", > "frOM" and so). > So my parser adds an instance variable @real_name within the header > name string ("FROM"). > > When I do the lookup of a header in the Request object, I would like > also to retrieve the key's @real_name, but I've already understood > that this is only possible if taint the key string before inserting it > in the hash and use Hash#assoc. This solution is not good for > performance. > > The solution suggested by Robert is adding such information (the > header original name) as a field in the hash entry value, so instead > of having: > > request["FROM"] > =3D> [ "sip:alice@xample.org ] > > I would end with something like: > > request["FROM"] > =3D> Struct ( "From", [ "sip:alice@xample.org ] ) > > The problem this last suggestion introduces is that it breaks the > existing API and makes more complext for a developer to handle the > Request class (which should be as easy as handling a Hash). > > > Thanks to both for your comments. > > -- > I=F1aki Baz Castillo > > > You don't have to have a hash to implement a hash interface. How about simply creating your own class that supports the interface you want, but also the functionality you want. Something like this: class Request Header =3D Struct.new :key , :value def self.parse(headers) request =3D Request.new headers.each_line do |header| key, value =3D header.split ": " request.add_header key , value.chomp end request end def initialize @headers =3D Hash.new end def add_header(key, value) @headers[key.upcase] =3D Header[key,value] end def [](key) @headers[key][:value] end def original(key) @headers[key][:key] end end headers =3D <
"sip:alice@example.org" request.original "FROM" # =3D> "frOM" request["TO"] # =3D> "sip:brad@example.org" request.original "TO" # =3D> "To" --0016e64cb1ead1d3cf04a10b7db9--