Odd hash behaviour

Hi all,

I'm still munging data and I'm struggling with Ruby's hash

For example, I want to store a value with an associated key (sounds like a hash or associated array), but I don't want duplicates (more like a set, in Java I'd use a HashSet to get this behaviour).

@min_pks = Hash.new()
....
# store value for key unless we already have it
@min_pks[min_key] = no unless @min_pks.has_key?(min_key)

Regardless of how I structure the above, the Hash always stores every value, it's as if the Hash always returns a false to the query has_key?, so it always stores a new value

The key I'm using is a 3 letter abbreviation like 'MID', 'MCY' etc, and in the incoming data they are duplicated

I've tried googling, I've tried ri etc, and there doesn't seem to be a Set class with Ruby (I'd rather not write my own), at least according to the docs. I'm also aware that the problem is between the keyboard and the chair, it's not Ruby's falut, I'm doing something dim.

Anyone help me out?

Kev

Hi all,

I'm still munging data and I'm struggling with Ruby's hash

For example, I want to store a value with an associated key (sounds like a hash or associated array), but I don't want duplicates (more like a set, in Java I'd use a HashSet to get this behaviour).

@min_pks = Hash.new()
....
# store value for key unless we already have it
@min_pks[min_key] = no unless @min_pks.has_key?(min_key)

Regardless of how I structure the above, the Hash always stores every value, it's as if the Hash always returns a false to the query has_key?, so it always stores a new value

As a Hash should. Keep in mind, that if you have a key 'foo' in your hash (let's say: @min_pks['foo'] => 42) and later you set 'foo' again (@min_pks['foo'] = 16) then @min_pks['foo'] is now 16, and the previous 42 value is gone (read: overwrote the previous value).

The key I'm using is a 3 letter abbreviation like 'MID', 'MCY' etc, and in the incoming data they are duplicated

I've tried googling, I've tried ri etc, and there doesn't seem to be a Set class with Ruby (I'd rather not write my own), at least according to the docs. I'm also aware that the problem is between the keyboard and the chair, it's not Ruby's falut, I'm doing something dim.

Ruby comes with a Set class; you just need to require it first. Consider:

require 'set'

your_set = Set.new ['foo', 42]

···

On 3-Oct-05, at 11:56 PM, Kev Jackson wrote:

Kev

--
Jeremy Tregunna
jtregunna@blurgle.ca

"If debugging is the process of removing bugs, then programming must be the process of putting them in." --Dykstra

Kev,
Seems to work for me ...
$ irb
irb(main):001:0> @min_pks = Hash.new()
=> {}
irb(main):002:0> key = 'MID'
=> "MID"
irb(main):003:0> @min_pks[key] = 1 unless @min_pks.has_key?(key)
=> 1
irb(main):004:0> @min_pks[key] = 2 unless @min_pks.has_key?(key)
=> nil
irb(main):005:0> p @min_pks
{"MID"=>1}
=> nil

Could you give the rest of your code and possibly some sample
data?

Vance

···

On Tue, 2005-10-04 at 12:56 +0900, Kev Jackson wrote:

Hi all,

I'm still munging data and I'm struggling with Ruby's hash

For example, I want to store a value with an associated key (sounds like
a hash or associated array), but I don't want duplicates (more like a
set, in Java I'd use a HashSet to get this behaviour).

@min_pks = Hash.new()
....
# store value for key unless we already have it
@min_pks[min_key] = no unless @min_pks.has_key?(min_key)

Regardless of how I structure the above, the Hash always stores every
value, it's as if the Hash always returns a false to the query has_key?,
so it always stores a new value

The key I'm using is a 3 letter abbreviation like 'MID', 'MCY' etc, and
in the incoming data they are duplicated

I've tried googling, I've tried ri etc, and there doesn't seem to be a
Set class with Ruby (I'd rather not write my own), at least according to
the docs. I'm also aware that the problem is between the keyboard and
the chair, it's not Ruby's falut, I'm doing something dim.

Anyone help me out?

Kev

Vance A Heron wrote:

Kev,
Seems to work for me ...
$ irb
irb(main):001:0> @min_pks = Hash.new()
=> {}
irb(main):002:0> key = 'MID'
=> "MID"
irb(main):003:0> @min_pks[key] = 1 unless @min_pks.has_key?(key)
=> 1
irb(main):004:0> @min_pks[key] = 2 unless @min_pks.has_key?(key)
=> nil
irb(main):005:0> p @min_pks
{"MID"=>1}
=> nil

Could you give the rest of your code and possibly some sample
data?

Actually it was working, but when printing out the values, it prints everything (ie including things that shouldn't have been in the Hash). I figured it all out in the end, my logic was a little twisted and the print was always executing (hence my confusion), the Hash was behaving perfectly.

As for the Set using

require 'Set'

That's the problem with not having docs for 1.8.2, the only docs I have cover 1.6 (and not too much of that). Suppose I'll have to get Pickaxe 2 :slight_smile:

Kev

my_hash = {} #=> {}
key = 'foo' #=> "foo"
my_hash[key] ||= 42 #=> 42
my_hash[key] ||= 10 #=> 42
my_hash[key] #=> 42 #=> 42

Don't forget ri:

C:\Documents and Settings\rjl>ri Set
------------------------------------------------------------- Class: Set
     Set implements a collection of unordered values with no duplicates.
     This is a hybrid of Array's intuitive inter-operation facilities
     and Hash's fast lookup.

     Several methods accept any Enumerable object (implementing +each+)
     for greater flexibility: new, replace, merge, subtract, |, &, -, ^.
...
[rest elided]

"ri -c" will also list all the classes ri knows about, in case you
aren't sure what you are looking for.

Ryan

···

On 10/4/05, Kev Jackson <kevin.jackson@it.fts-vn.com> wrote:

That's the problem with not having docs for 1.8.2, the only docs I have
cover 1.6 (and not too much of that). Suppose I'll have to get Pickaxe 2 :slight_smile:

Or http://www.ruby-doc.org/\.

James Edward Gray II

···

On Oct 4, 2005, at 12:26 AM, Ryan Leavengood wrote:

On 10/4/05, Kev Jackson <kevin.jackson@it.fts-vn.com> wrote:

That's the problem with not having docs for 1.8.2, the only docs I have
cover 1.6 (and not too much of that). Suppose I'll have to get Pickaxe 2 :slight_smile:

Don't forget ri:

In case you've been to ruby-doc and were confused, use the "Core API" and "Std Lib" links at the top to get started.

···

On Oct 4, 2005, at 7:13 AM, James Edward Gray II wrote:

That's the problem with not having docs for 1.8.2, the only docs I have
cover 1.6 (and not too much of that). Suppose I'll have to get Pickaxe 2 :slight_smile:

Or http://www.ruby-doc.org/\.