Hi, I’d like to extend Hash class [] and []= methods in order to find a
key
with case insensitive. This is:
- The actual Hash [] behaviour:
{“a”=>1,“b”=>2}[“a”]
=> 1
{“a”=>1,“b”=>2}[“A”]
=> nil
{“a”=>1,“b”=>2}[“a”]
=> 1
{“a”=>1,“b”=>2}[“A”]
=> 1
But I can’t modify [] method since it’s Ruby core written in C:
VALUE
rb_hash_aref(hash, key)
VALUE hash, key;
{
VALUE val;
if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
return rb_funcall(hash, id_default, 1, key);
}
return val;
}
How could I do it?
Hi –
On Wed, 23 Apr 2008, Iñaki Baz C. wrote:
}
How could I do it?
You can reopen the Hash class in Ruby, but it’s not a good idea to
change the documented behavior of core methods. A better way is to
write a module, and then use it selectively for the hashes that need
it:
module CaseInsensitiveLookup
def
etc., and then:
my_hash.extend(CaseInsensitiveLookup)
David
El Miércoles, 23 de Abril de 2008, David A. Black escribió:
A better way is to
write a module, and then use it selectively for the hashes that need
it:
  module CaseInsensitiveLookup
   def
Yes, but my question is what to do into that:
def " method
…
end
since the original code is written in C and I don’t know which
attributes
should I use to access to keys and values.
Hi,
You can use super and/or alias:
class MyHash < Hash
def [] key
super(key.downcase)
end
end
Dan
On Apr 22, 6:15 pm, Daniel F. [email protected] wrote:
Hi,
You can use super and/or alias:
class MyHash < Hash
def [] key
super(key.downcase)
end
end
But he asking for case-insensitivity. If a key is created with
uppercase letters, you’re out of luck. And if you look for a value
for a non-string key, that’s no good either:
class MyHash < Hash
def
super(key.downcase)
end
end
h = MyHash.new
h[‘A’] = ‘never findable’
h[‘A’] # => nil
h[1] # ~> undefined method `downcase’ for 1:Fixnum (NoMethodError)
You could override []= as well (and with more care), but I wonder if a
different class with a Hash instance variable with mediated access
would be a better route.
Chris
El Miércoles, 23 de Abril de 2008, Daniel F.
escribió:> Dan
opss, yes, it was no so difficult XDD
Thanks a lot.
On Apr 22, 7:31 pm, Chris S. [email protected] wrote:
end
end
Chris
Or just use Rubinius: http://pastie.textmate.org/185232
!!!
Chris
2008/4/23, Chris S. [email protected]:
Or just use Rubinius: http://pastie.textmate.org/185232
Or delegation
h = CiHash.new
h[“FOO”]=1
h[:not_a_string]=2 # works, too
puts h[“foo”]
puts h[:not_a_string]
Cheers
robert
2008/4/23, Robert K. [email protected]:
2008/4/23, Chris S. [email protected]:
Or just use Rubinius: http://pastie.textmate.org/185232
Or delegation
Copy and paste error: this was missing:
require ‘delegate’
class CiHash < DelegateClass(Hash)
def initialize
super({})
end
def []=(k,v)
getobj[(k.downcase rescue k)] = v
end
def
getobj[(k.downcase rescue k)]
end
add other lookup and mutation methods
end
2008/4/23, Iñaki Baz C. [email protected]:
class InsensitiveHash < Hash
def [](key)
find {|h| h[0] =~ /^#{key}$/i }[1]
end
end
It works. 
… and is awfully inefficient.
Here’s another way, which is more efficient for large hashes
class CiHash2 < DelegateClass(Hash)
CiString = Struct.new :string do
def to_s; string.downcase end
def hash; string.downcase.hash end
def eql?(s) string.downcase.eql? s.string.downcase end
alias == eql?
def inspect; string.inspect; end
end
def initialize
super({})
end
def []=(k,v)
k = CiString.new(k) if String === k
getobj[k] = v
end
def
k = CiString.new(k) if String === k
getobj[k]
end
add other lookup and mutation methods
end
h = CiHash2.new
h[“FOO”]=3
h[“Foo”]=4
puts h[“foo”]
puts h[“fOo”]
p h
Cheers
robert
2008/4/23, Chris S. [email protected]:
But he asking for case-insensitivity. If a key is created with
uppercase letters, you’re out of luck. And if you look for a value
for a non-string key, that’s no good either:
Yeah, finally I’ve done:
class InsensitiveHash < Hash
def [](key)
find {|h| h[0] =~ /^#{key}$/i }[1]
end
end
It works. 
2008/4/23, Robert K. [email protected]:
… and is awfully inefficient.
Here’s another way, which is more efficient for large hashes
Oh, thanks, I’ll spend some time investigating what your solution (or
how) does 
Thanks.