Checking hash key's and values, with case insensitivity

Hey all,

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and ".has_value?"
methods. I believe these are case sensitive by default.

Thanks,

  • Khurram

Hi –

···

On Fri, 20 Sep 2002, Khurram wrote:

Hey all,

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

If you set the global variable $= to true, they will not be
case sensitive. But neither will regex matches, so use with
caution. (You can set it back to false of course.)

David


David Alan Black | Register for RubyConf 2002!
home: dblack@candle.superlink.net | November 1-3
work: blackdav@shu.edu | Seattle, WA, USA
Web: http://pirate.shu.edu/~blackdav | http://www.rubyconf.com

class Hash
def has_ikey?(key)
self.keys.map { |key| key.upcase }.member? key.upcase
end
end

hash = {"foo" => 1, "bar" => 2}

hash.has_ikey? "foo"    # => true
hash.has_ikey? "FOO"    # => true
hash.has_ikey? "Foo"    # => true

hash.has_ikey? "quux"   # => false

– Dossy

···

On 2002.09.20, Khurram khabibiuf@hotmail.com wrote:

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

Hi,

···

In message “Checking hash key’s and values, with case insensitivity” on 02/09/20, Khurram khabibiuf@hotmail.com writes:

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

Why not simply

h.key?(k.upcase)
h.value?(v.upcase)

						matz.

Doesn’t iterating through all the keys on a lookup kindof take away the
advantages of a hashtable? :slight_smile:

Tom.

···

On 2002.09.20, Khurram khabibiuf@hotmail.com wrote:

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

class Hash
  def has_ikey?(key)
    self.keys.map { |key| key.upcase }.member? key.upcase
  end
end


.^. .-------------------------------------------------------.
/V\ | Tom Gilbert, London, England | http://linuxbrit.co.uk |
/( )\ | Open Source/UNIX consultant | tom@linuxbrit.co.uk |
^^-^^ `-------------------------------------------------------’

This has got to be the best solution, as it takes account of the important fact
that noone else has yet mentioned: Hash keys are not necessarily Strings.

Gavin

···

----- Original Message -----
From: “Yukihiro Matsumoto” matz@ruby-lang.org

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

Why not simply

h.key?(k.upcase)
h.value?(v.upcase)

matz.

If you’re looking for case insensitive hashes you’re already
going to hell.

Isn’t the whole constraint of a hashtable is that it’s case sensitive?

– Dossy

···

On 2002.09.21, Tom Gilbert tom@linuxbrit.co.uk wrote:

On 2002.09.20, Khurram khabibiuf@hotmail.com wrote:

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

class Hash
  def has_ikey?(key)
    self.keys.map { |key| key.upcase }.member? key.upcase
  end
end

Doesn’t iterating through all the keys on a lookup kindof take away the
advantages of a hashtable? :slight_smile:


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

Sat, 21 Sep 2002 00:32:27 +0900, Dossy dossy@panoptic.com pisze:

If you’re looking for case insensitive hashes you’re already going
to hell.

Nope. But apart from the evil $= I’m afraid Ruby doesn’t provide a way
to use different equality and hashing functions in a particular hash,
other than wrapping keys in different objects.

Usually an alternative hash and equality are made by composing
a particular function with standard hash and equality. So it would
be nice to have a shortcut for that:
Hash.new (‘by’ => proc {|s| s.downcase})
It would store keys as they were given and look them up downcased.

It looks a bit ugly because Ruby has only one block per method (and the
block for Hash.new is already used), and there is no nicer substitute
for keyword arguments, and a proc which calls a given method must be
written in full that long. In my language it will look like this:
dict (by: 'downcase)

I haven’t encountered any other need for that than case insensitive
strings though.

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ Blog człowieka poczciwego.

Hi –

From: “Yukihiro Matsumoto” matz@ruby-lang.org

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

Why not simply

h.key?(k.upcase)
h.value?(v.upcase)

matz.

This has got to be the best solution, as it takes account of the important fact
that noone else has yet mentioned: Hash keys are not necessarily Strings.

What if the key you used is lowercase? like this:

irb(main):002:0> h = {“a” => 1}
{“a”=>1}
irb(main):003:0> k = “a”
“a”
irb(main):004:0> h.key?(k)
true
irb(main):005:0> h.key?(k.upcase)
false

David

···

On Tue, 24 Sep 2002, Gavin Sinclair wrote:

----- Original Message -----


David Alan Black | Register for RubyConf 2002!
home: dblack@candle.superlink.net | November 1-3
work: blackdav@shu.edu | Seattle, WA, USA
Web: http://pirate.shu.edu/~blackdav | http://www.rubyconf.com

Isn't the whole constraint of a hashtable is that it's case sensitive?

No, with '$= = true' it's case insensitive

For example :

pigeon% cat b.rb
#!/usr/bin/ruby
$= = true

a = {"aaa" => 12, "BbB" => 12}
p a["bbb"]

$= = false
p a["BbB"]
a.rehash
p a["BbB"]
pigeon%

pigeon% b.rb
12
nil
12
pigeon%

The hash was created with `$= = true' when you switch to `$= = false' you
must call #rehash to recompute the hashtable.

Guy Decoux

Dossy dossy@panoptic.com writes:

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

class Hash
  def has_ikey?(key)
    self.keys.map { |key| key.upcase }.member? key.upcase
  end
end

Doesn’t iterating through all the keys on a lookup kindof take away the
advantages of a hashtable? :slight_smile:

If you’re looking for case insensitive hashes you’re already
going to hell.

Isn’t the whole constraint of a hashtable is that it’s case sensitive?

if you do not need the case-information of your hash-keys at all you
could mangle the key to lowercase in the = and methods

class Hash_I < Hash

alias get_old
alias set_old =

def
return get_old(key.to_s.upcase)
end

def =(key, value)
return set_old(key.to_s.upcase, value)
end

end

if i needed both (case-sensitive keys and case-insensitive member?-
lookups), i would use a second auxiliary-hash in the class above.

regards
messju

···

On 2002.09.21, Tom Gilbert tom@linuxbrit.co.uk wrote:

On 2002.09.20, Khurram khabibiuf@hotmail.com wrote:

– Dossy

“Dossy” dossy@panoptic.com wrote in message
news:20020920153223.GZ27665@panoptic.com

If you’re looking for case insensitive hashes you’re already
going to hell.

Isn’t the whole constraint of a hashtable is that it’s case sensitive?

– Dossy

The way to deal with this is to create a hashtable that is indexed by
normalized keys i.e. all uppercase or all lowercase characters. Upon lookup
you map the search key the same way. The actual hash lookup is still case
sensitive. You may then store the original key as a value and you may also
want to maintain two hashes - one with the original keys and one with the
normalized keys.

Mikkel

Hi –

From: “Yukihiro Matsumoto” matz@ruby-lang.org

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

Why not simply

h.key?(k.upcase)
h.value?(v.upcase)

matz.

This has got to be the best solution, as it takes account of the important
fact
that noone else has yet mentioned: Hash keys are not necessarily Strings.

What if the key you used is lowercase? like this:

irb(main):002:0> h = {“a” => 1}
{“a”=>1}
irb(main):003:0> k = “a”
“a”
irb(main):004:0> h.key?(k)
true
irb(main):005:0> h.key?(k.upcase)
false

I think Matz intended that the keys get case-neutralised upon entry into the
hash. Naturally, that stuffs you if you input both “Key” and “kEy” into the
hash, but as someone pointed out, if genuine case-insensitive retrieval is what
you want, then hash is not what you need.

May I suggest a binary tree or similar structure, in case the original poster
is still interested?

Gavin

···

----- Original Message -----
From: dblack@candle.superlink.net

On Tue, 24 Sep 2002, Gavin Sinclair wrote:

----- Original Message -----

Tue, 24 Sep 2002 15:43:41 +0900, Gavin Sinclair gsinclair@soyabean.com.au pisze:

I think Matz intended that the keys get case-neutralised upon entry into the
hash. Naturally, that stuffs you if you input both “Key” and “kEy” into the
hash, but as someone pointed out, if genuine case-insensitive retrieval is what
you want, then hash is not what you need.

A hash table is as good for a case-insensitive dictionary as for a
case-sensitive one. Just use appropriate equality and hash function.

If equality is known to work like this. f(k1) == f(k2) (for some
function f) and hashing is f(k).hash, then a better implementation
is to cache values of f for all keys.

Ruby’s Hash can’t use explicitly-provided equality and hashing, right?
So a programmer it’s forced to cache them, and store unmodified keys
elsewhere if case should be preserved.

In my language I would write ‘hashMap (by: lowercase)’ to obtain a
case-insensitive hash. The implementation must use a somewhat changed
representation to store both original and transformed keys.

In Ruby it would be something like Hash.new_by {|k| k.tolower},
except that the block for a constructor conflicts with specifying
the behavior on absent keys - Ruby methods take at most one block.
So maybe something like Hash.new(by => proc {|k| k.tolower})?

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/

Out of curiosity, where is $= actually documented? I found no mention
of it in any of the three Ruby books I have (Nutshell, Pickaxe, Ruby Way).

And do what if you have two keys in the original hash if they are equal
when ignoring the case?

···

On Sat, Sep 21, 2002 at 01:43:10AM +0900, MikkelFJ wrote:

“Dossy” dossy@panoptic.com wrote in message
news:20020920153223.GZ27665@panoptic.com

If you’re looking for case insensitive hashes you’re already
going to hell.

Isn’t the whole constraint of a hashtable is that it’s case sensitive?

– Dossy

The way to deal with this is to create a hashtable that is indexed by
normalized keys i.e. all uppercase or all lowercase characters. Upon lookup
you map the search key the same way. The actual hash lookup is still case
sensitive. You may then store the original key as a value and you may also
want to maintain two hashes - one with the original keys and one with the
normalized keys.


Meisterbohne Söflinger Straße 100 Tel: +49-731-399 499-0
eLösungen 89077 Ulm Fax: +49-731-399 499-9

“Gavin Sinclair” gsinclair@soyabean.com.au wrote in message news:021001c26395$ab204190$b14332d2@nosedog

From: dblack@candle.superlink.net

Hi –

From: “Yukihiro Matsumoto” matz@ruby-lang.org

How can I check hash keys and values without case sensitivity?
Specifically I’m referring to the hash “.has_key?” and “.has_value?”
methods. I believe these are case sensitive by default.

Why not simply

h.key?(k.upcase)
h.value?(v.upcase)

matz.

This has got to be the best solution, as it takes account of the important
fact
that noone else has yet mentioned: Hash keys are not necessarily Strings.

What if the key you used is lowercase? like this:

irb(main):002:0> h = {“a” => 1}
{“a”=>1}
irb(main):003:0> k = “a”
“a”
irb(main):004:0> h.key?(k)
true
irb(main):005:0> h.key?(k.upcase)
false

I think Matz intended that the keys get case-neutralised upon entry into the
hash. Naturally, that stuffs you if you input both “Key” and “kEy” into the
hash, but as someone pointed out, if genuine case-insensitive retrieval is what
you want, then hash is not what you need.

May I suggest a binary tree or similar structure, in case the original poster
is still interested?

Gavin

this seems to work in all situations (implementation below) :

h = Hash.new
h.case_numb
h[‘k’] = ‘v’

puts h.has_key? ‘K’ -->> false

h.ignoring_case do
puts h.has_key? ‘K’ -->> true
end

this code relies on mapping each case insensive key to it’s list of
actual keys, and the same for values, eg.

h = {‘abc’ => ‘def’, ‘aBc’ => ‘dEf’}

h.ci_keys =
{‘ABC’ => {‘abc’ => ‘def’, ‘aBc’ => ‘dEf’}}

h.ci_vals =
{‘DEF’ => {‘def’ => ‘abc’, ‘dEf’ => ‘aBc’}}

(you could just map everything to true…)

implementaion follows - this ones silly, but the idea of tracking
information about case insensitivity and allowing the object to
‘sometimes’ use it is usefull i think…

-ara

module CIHashMethods

attr :ci_keys, true
attr :ci_vals, true
attr :ci, true

def CIHashMethods.extend_object aHash
super
aHash.ci_keys = Hash.new
aHash.ci_vals = Hash.new
aHash.ci = false
end

def = k, v
(self.ci_keys[k.upcase] ||= Hash.new)[k] = v
(self.ci_vals[v.upcase] ||= Hash.new)[v] = k
super k, v
end

def has_key? k
self.ci and return self.ci_keys.has_key? k.upcase
super k
end

def has_val? v
self.ci and return self.ci_vals.has_value? v.upcase
super v
end

def ignoring_case(&block)
begin
self.ci = true
yield block
ensure
self.ci = false
end
end
end

class CIHash < Hash
include CIHashMethods
end
class Hash
def case_numb
self.extend CIHashMethods
end
end

···

----- Original Message -----

On Tue, 24 Sep 2002, Gavin Sinclair wrote:

----- Original Message -----

I have a couple of HUGE hashes (~20,000 pairs and growing) that I need
to sort. These are in the form of:

{
“foo”=>[“fee”,“fi”],
“bar”=>[“fee”,“fi”,“fo”],
“baz”=>[“fee”,“fi”,“fo”,“fum”],
:
:
}

I want to be able to sort them in the order of the array size (each of
the element has a special variable-sized array. So that I can dump them
in another array and indexed in ascending order.

sorted_stuff[0] = [“foo”, [“fee”,“fi”]] #array size = 2
sorted_stuff[1] = [“bar”, [“fee”,“fi”,“fo”]] #array size = 3
sorted_stuff[1] = [“bar”, [“fee”,“fi”,“fo”,“fum”]] #array size = 4

What is the scalable way to do this? I’m looking at scaling these hashes
beyond 50K…

···


Wai-Sun “Squidster” Chia
Consulting & Integration
Linux/Unix/Web Developer Dude

Out of curiosity, where is $= actually documented? I found no mention
of it in any of the three Ruby books I have (Nutshell, Pickaxe, Ruby Way).

  Pickaxe p 216

Guy Decoux

Overall, if your application code doesn’t already expect normalized
hash keys, I think I agree with dossy. :slight_smile: For this application case
collision on the keys something that needs to be handled regardless of
the storage scheme. It’s just a matter of where you want to handle
before storing the value, or after.

I don’t have the earlier posts in the thread, but how was it going to
be handled orginally? For this scheme,

If you want case insensitive hash keys always, I’d just normalize the keys
before storing the value. Case collisions overwrite the value.

If you want case sensitive on store, and case insensitive on retreive
then you could store an array of the possible matching keys, check for
an array and trigger the same “case collision” logic as in the
original case.

Cheers,
alan

···

On Sat, Sep 21, 2002 at 04:09:51AM +0900, Philipp Meier wrote:

On Sat, Sep 21, 2002 at 01:43:10AM +0900, MikkelFJ wrote:

“Dossy” dossy@panoptic.com wrote in message
news:20020920153223.GZ27665@panoptic.com

If you’re looking for case insensitive hashes you’re already
going to hell.

Isn’t the whole constraint of a hashtable is that it’s case sensitive?

– Dossy

The way to deal with this is to create a hashtable that is indexed by
normalized keys i.e. all uppercase or all lowercase characters. Upon lookup
you map the search key the same way. The actual hash lookup is still case
sensitive. You may then store the original key as a value and you may also
want to maintain two hashes - one with the original keys and one with the
normalized keys.

And do what if you have two keys in the original hash if they are equal
when ignoring the case?


Alan Chen
Digikata LLC
http://digikata.com