Hash or bidimensional Array when key is case insensitive?

Hi, I've to take a decission about using an bidimensional Array or a
Hash to store parameters. Of course I prefer Hash since the order
doesn't matter and I know the param name I'll need.
The problem is that the param name is case insensitive.

Example:

  tag = qweqweqwe
  Method = INVITE
  NAT=yes

is the same as:

  Tag = qweqweqwe
  METHOD = INVITE
  Nat=yes

If I use an bidimensional Array and need to get "method" param I willl
need to do:

  method = params_array.find { |param| param[0] =~ /^method$/i }[1]

And if I use a Hash I'll do the same:

  method = params_hash.find { |param| param[0] =~ /^method$/i }[1]

Is there any advantage using Array or Hash in my case (key is case insensitive)?

Thanks a lot for any suggestion.

···

--
Iñaki Baz Castillo
<ibc@aliax.net>

Iñaki Baz Castillo wrote:

And if I use a Hash I'll do the same:

  method = params_hash.find { |param| param[0] =~ /^method$/i }[1]

Use a hash and lowercase the keys. If you need to preserve the original
casing, do that in the value, e.g. like this: {key.lowercase => [key,
value], ...}
Another approach would be a special Key class which is like String but
has #hash and #eql? redefined to work as if the String was lowercased.
There probably are more approaches.

Regards
Stefan

···

--
Posted via http://www.ruby-forum.com/\.

Another approach is to store it in a hash, but downcase the key before
storing and retreiving:

irb(main):001:0> h = {"get" => "value_for_get", "post" => "value_for_post"}
=> {"get"=>"value_for_get", "post"=>"value_for_post"}
irb(main):002:0> method = "gEt"
=> "gEt"
irb(main):003:0> h[method.downcase]
=> "value_for_get"

Jesus.

···

On Tue, Apr 15, 2008 at 6:31 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

Hi, I've to take a decission about using an bidimensional Array or a
Hash to store parameters. Of course I prefer Hash since the order
doesn't matter and I know the param name I'll need.
The problem is that the param name is case insensitive.

Example:

  tag = qweqweqwe
  Method = INVITE
  NAT=yes

is the same as:

  Tag = qweqweqwe
  METHOD = INVITE
  Nat=yes

If I use an bidimensional Array and need to get "method" param I willl
need to do:

  method = params_array.find { |param| param[0] =~ /^method$/i }[1]

And if I use a Hash I'll do the same:

  method = params_hash.find { |param| param[0] =~ /^method$/i }[1]

Is there any advantage using Array or Hash in my case (key is case insensitive)?

Thanks, but the problem is exactly the opposite: I receive a request that can
contain parameter name in low or uppercase, and I need to process them but
keeping them untouched to forward the request to other location.

Thanks a lot.

···

El Martes, 15 de Abril de 2008, Jesús Gabriel y Galán escribió:

Another approach is to store it in a hash, but downcase the key before
storing and retreiving:

irb(main):001:0> h = {"get" => "value_for_get", "post" => "value_for_post"}
=> {"get"=>"value_for_get", "post"=>"value_for_post"}
irb(main):002:0> method = "gEt"
=> "gEt"
irb(main):003:0> h[method.downcase]
=> "value_for_get"

--
Iñaki Baz Castillo

Iñaki Baz Castillo wrote:
> And if I use a Hash I'll do the same:
>
> method = params_hash.find { |param| param[0] =~ /^method$/i }[1]

Use a hash and lowercase the keys. If you need to preserve the original
casing, do that in the value, e.g. like this: {key.lowercase => [key,
value], ...}

Ah ok, it's a good idea :slight_smile:

Another approach would be a special Key class which is like String but
has #hash and #eql? redefined to work as if the String was lowercased.

Thanks but I don't understnad this point. Do you mean extending the Hash
class? I don't think so since there is not any Key class. Could you please
explain in more detail you suggestion?

Thanks a lot for all.

···

El Martes, 15 de Abril de 2008, Stefan Rusterholz escribió:

--
Iñaki Baz Castillo

If I understand you correctly, in my snippet above, the variable
method will contain what you receive. You downcase it for searching in
the hash, but still have the original string to pass it along. Am I
right? Maybe I am getting the order of your stuff wrong. Can you post
an example of what you have?

Jesus.

···

On Tue, Apr 15, 2008 at 10:50 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

El Martes, 15 de Abril de 2008, Jesús Gabriel y Galán escribió:

> Another approach is to store it in a hash, but downcase the key before
> storing and retreiving:
>
> irb(main):001:0> h = {"get" => "value_for_get", "post" => "value_for_post"}
> => {"get"=>"value_for_get", "post"=>"value_for_post"}
> irb(main):002:0> method = "gEt"
> => "gEt"
> irb(main):003:0> h[method.downcase]
> => "value_for_get"

Thanks, but the problem is exactly the opposite: I receive a request that can
contain parameter name in low or uppercase, and I need to process them but
keeping them untouched to forward the request to other location.

> Iñaki Baz Castillo wrote:
> > And if I use a Hash I'll do the same:
> >
> > method = params_hash.find { |param| param[0] =~ /^method$/i }[1]
>
> Use a hash and lowercase the keys. If you need to preserve the original
> casing, do that in the value, e.g. like this: {key.lowercase => [key,
> value], ...}

Ah ok, it's a good idea :slight_smile:

Hey, now I got your requirements !! Please ignore my other post...

> Another approach would be a special Key class which is like String but
> has #hash and #eql? redefined to work as if the String was lowercased.

Thanks but I don't understnad this point. Do you mean extending the Hash
class? I don't think so since there is not any Key class. Could you please
explain in more detail you suggestion?

What he means is that instead of lowercasing the key before inserting
in the hash, you create a Key class in a way that the hash will think
two keys are the same if they have the same string ignoring case.
Something like (not tested):

class Key
  attr_reader :key
  def initialize key
    @key = key
   end

  def hash
    @key.downcase.hash
  end

  def eql? other
    @key.downcase.eql? other.downcase
  end
end

and then you populate the hash as:

h[Key.new(method)] = [method, values_for_method]

this way you locate the entry in the hash ignoring case and have the
original value in the value of the hash.

Hope I've explained myself...

Jesus.

···

On Tue, Apr 15, 2008 at 11:27 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

El Martes, 15 de Abril de 2008, Stefan Rusterholz escribió:

Sure, it's cool :slight_smile:

Thanks a lot to both.

···

El Martes, 15 de Abril de 2008, Jesús Gabriel y Galán escribió:

> Thanks but I don't understnad this point. Do you mean extending the Hash
> class? I don't think so since there is not any Key class. Could you
> please explain in more detail you suggestion?

What he means is that instead of lowercasing the key before inserting
in the hash, you create a Key class in a way that the hash will think
two keys are the same if they have the same string ignoring case.
Something like (not tested):

class Key
  attr_reader :key
  def initialize key
    @key = key
   end

  def hash
    @key.downcase.hash
  end

  def eql? other
    @key.downcase.eql? other.downcase
  end
end

and then you populate the hash as:

h[Key.new(method)] = [method, values_for_method]

this way you locate the entry in the hash ignoring case and have the
original value in the value of the hash.

Hope I've explained myself...

--
Iñaki Baz Castillo