Hash == not always working? Or am I missing something?

W

walter

Hi everyone,


I am having difficulty with Hash and sometimes Arrays with ==. Below
is an example with Hashes. I am trying to do some simple cleanup of
our data and was trying TDD some code but I do not understand why it
says my 2 Hashes are different. They appear identical but show up as
false using ==.

According to ri :
----------------------------------------------------------------
Hash#==
hsh == anOtherHash -> true or false
----------------------------------------------------------------------
--
Equality---Two hashes are equal if they each contain the same
number of keys and if each key-value pair is equal to (according
to
Object#==) the corresponding elements in the other hash.
h1 = { "a" => 1, "c" => 2 }
h2 = { 7 => 35, "c" => 2, "a" => 1 }
h3 = { "a" => 1, "c" => 2, 7 => 35 }
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h1 == h2 #=> false
h2 == h3 #=> true
h3 == h4 #=> false



This should work. The code is below along with the Test::Unit
output.


Am I missing something stupid????


<CODE>

module ShipToCleanUp
def notes
results = []
1.upto(6) do |i|
results << send("note#{i}")
end
results.join(" ").strip
end

def word_counts
results = Hash.new{|h,k| h[k] = 0}
notes.split(/\s+/).each{|word| results[word]+=1}
results
end
end


if __FILE__ == $0
require 'test/unit'
class ShipToCleanUpTester < Test::Unit::TestCase
class ShipTo
include ShipToCleanUp
attr_accessor :note1, :note2, :note3, :note4, :note5, :note6
def initialize(n1='', n2='', n3='', n4='', n5='', n6='')
@note1, @note2, @note3, @note4, @note5, @note6 = n1, n2, n3,
n4, n5, n6
end
end

def setup
@shipTo1 = ShipTo.new('LINE 1 AND SOME MORE ON LINE 1 ', '
***** LINE 2 ***** ', '', '', 'LINE 5 ', 'AND LINE 6')
end

def test_word_counts
expected = {}
expected['LINE'] = 5
expected['1'] = 2
expected['AND'] = 2
expected['SOME'] = 1
expected['MORE'] = 1
expected['ON'] = 1
expected['*****'] = 2
expected['2'] = 1
expected['5'] = 1
expected['6'] = 1

assert_equal(expected, @shipTo1.word_counts)
end

def test_notes_some_empty
expected = "1 6"
assert_equal(expected, ShipTo.new("1", '', '', '', '',
'6').notes)
end

def test_notes_empty
expected = ""
assert_equal(expected, ShipTo.new.notes)
end

def test_notes
expected = "LINE 1 AND SOME MORE ON LINE 1 ***** LINE 2
***** LINE 5 AND LINE 6"
assert_equal(expected, @shipTo1.notes)
end
end
end

</CODE>


When I run the code I get

Loaded suite C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/rbC.tmp
Started
...F
Finished in 0.04 seconds.

1) Failure:
test_word_counts(ShipToCleanUpTester)
[C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/rbC.tmp:46]:
<{"6"=>1,
"AND"=>2,
"LINE"=>5,
"*****"=>2,
"1"=>2,
"2"=>1,
"ON"=>1,
"SOME"=>1,
"5"=>1,
"MORE"=>1}> expected but was
<{"6"=>1,
"AND"=>2,
"LINE"=>5,
"*****"=>2,
"1"=>2,
"2"=>1,
"ON"=>1,
"SOME"=>1,
"5"=>1,
"MORE"=>1}>.

4 tests, 4 assertions, 1 failures, 0 errors




Any insight would be greatly appreciated.


Thanks,

Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
T

ts

w> results = Hash.new{|h,k| h[k] = 0}

[...]

w> expected = {}

your 2 Hash are not the same : they don't use the same default value


Guy Decoux
 
S

Simon Strandgaard

I am having difficulty with Hash and sometimes Arrays with ==. Below
is an example with Hashes. I am trying to do some simple cleanup of
our data and was trying TDD some code but I do not understand why it
says my 2 Hashes are different. They appear identical but show up as
false using ==.

I see you make usage of #default_proc.. but the Hash you
compare against does't contains a equal #default_proc.


server> ri Hash.default_proc
------------------------------------------------------ Hash#default_proc
hsh.default_proc -> anObject
------------------------------------------------------------------------
If +Hash::new+ was invoked with a block, return that block,
otherwise return +nil+.

h = Hash.new {|h,k| h[k] = k*k } #=> {}
p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
a = [] #=> []
p.call(a, 2)
a #=> [nil, nil, 4]

server>
 
W

walter

w> results = Hash.new{|h,k| h[k] = 0}

[...]

w> expected = {}

your 2 Hash are not the same : they don't use the same default value


Guy Decoux


So even though the items are the same, that doesn't matter if the
default value is different. Why would that be? And if so, should ri
be updated to reflect this (or have newer version already been
updated (I am using 1.8.1r11 Prag-Prog installer)?


Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
W

walter

w> results = Hash.new{|h,k| h[k] = 0}

[...]

w> expected = {}

your 2 Hash are not the same : they don't use the same default value


Guy Decoux

Thanks for the response Guy,


I changed both hashes to be created by Hash.new{|h,k| h[k] = 0} but I
still get the error.....



<code>
module ShipToCleanUp
def notes
results = []
1.upto(6) do |i|
results << send("note#{i}")
end
results.join(" ").strip
end

def word_counts
results = Hash.new{|h,k| h[k] = 0}
notes.split(/\s+/).each{|word| results[word]+=1}
results
end
end


if __FILE__ == $0
require 'test/unit'
class ShipToCleanUpTester < Test::Unit::TestCase
class ShipTo
include ShipToCleanUp
attr_accessor :note1, :note2, :note3, :note4, :note5, :note6
def initialize(n1='', n2='', n3='', n4='', n5='', n6='')
@note1, @note2, @note3, @note4, @note5, @note6 = n1, n2, n3,
n4, n5, n6
end
end

def setup
@shipTo1 = ShipTo.new('LINE 1 AND SOME MORE ON LINE 1 ', '
***** LINE 2 ***** ', '', '', 'LINE 5 ', 'AND LINE 6')
end

def test_word_counts
expected = Hash.new{|h,k| h[k] = 0}
expected['LINE'] = 5
expected['1'] = 2
expected['AND'] = 2
expected['SOME'] = 1
expected['MORE'] = 1
expected['ON'] = 1
expected['*****'] = 2
expected['2'] = 1
expected['5'] = 1
expected['6'] = 1

assert_equal(expected, @shipTo1.word_counts)
end

def test_notes_some_empty
expected = "1 6"
assert_equal(expected, ShipTo.new("1", '', '', '', '',
'6').notes)
end

def test_notes_empty
expected = ""
assert_equal(expected, ShipTo.new.notes)
end

def test_notes
expected = "LINE 1 AND SOME MORE ON LINE 1 ***** LINE 2
***** LINE 5 AND LINE 6"
assert_equal(expected, @shipTo1.notes)
end
end
end
</code>

<output>
Loaded suite C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/rbC.tmp
Started
...F
Finished in 0.04 seconds.

1) Failure:
test_word_counts(ShipToCleanUpTester)
[C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/rbC.tmp:46]:
<{"6"=>1,
"AND"=>2,
"LINE"=>5,
"*****"=>2,
"1"=>2,
"2"=>1,
"ON"=>1,
"SOME"=>1,
"5"=>1,
"MORE"=>1}> expected but was
<{"6"=>1,
"AND"=>2,
"LINE"=>5,
"*****"=>2,
"1"=>2,
"2"=>1,
"ON"=>1,
"SOME"=>1,
"5"=>1,
"MORE"=>1}>.

4 tests, 4 assertions, 1 failures, 0 errors
</output>
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
F

Florian Frank

I am having difficulty with Hash and sometimes Arrays with ==. Below
is an example with Hashes. I am trying to do some simple cleanup of
our data and was trying TDD some code but I do not understand why it
says my 2 Hashes are different. They appear identical but show up as
false using ==.

You compare a hash created with a block argument to a hash created
without a block argument. That's why they are not equal. Actually it's
complicated to compare such hashes.

You can implement a workaround like that:

$block = lambda {|h,k| h[k] = 0}
hash1 = Hash.new(&$block)
hash2 = Hash.new(&$block)

Perhaps it would be easier to just use
hash = Hash.new(0)
for your hashes.
 
T

ts

Try this


class MyHash < Hash
def default(k)
self[k] = 0
end
end

w> module ShipToCleanUp
w> def notes
w> results = []
w> 1.upto(6) do |i|
w> results << send("note#{i}")
w> end
w> results.join(" ").strip
w> end

w> def word_counts
w> results = Hash.new{|h,k| h[k] = 0}

results = MyHash.new

w> notes.split(/\s+/).each{|word| results[word]+=1}
w> results
w> end
w> end


w> if __FILE__ == $0
w> require 'test/unit'
w> class ShipToCleanUpTester < Test::Unit::TestCase
w> class ShipTo
w> include ShipToCleanUp
w> attr_accessor :note1, :note2, :note3, :note4, :note5, :note6
w> def initialize(n1='', n2='', n3='', n4='', n5='', n6='')
w> @note1, @note2, @note3, @note4, @note5, @note6 = n1, n2, n3,
w> n4, n5, n6
w> end
w> end

w> def setup
w> @shipTo1 = ShipTo.new('LINE 1 AND SOME MORE ON LINE 1 ', '
w> ***** LINE 2 ***** ', '', '', 'LINE 5 ', 'AND LINE 6')
w> end

w> def test_word_counts
w> expected = Hash.new{|h,k| h[k] = 0}

expected = MyHash.new

w> expected['LINE'] = 5



Guy Decoux
 
Y

Yukihiro Matsumoto

Hi,

In message "Hash == not always working? Or am I missing something?"

|I am having difficulty with Hash and sometimes Arrays with ==. Below
|is an example with Hashes. I am trying to do some simple cleanup of
|our data and was trying TDD some code but I do not understand why it
|says my 2 Hashes are different. They appear identical but show up as
|false using ==.

Because they have different default proc (the one has none, the other
have {|h,k| h[k] = 0}. The document should have mentioned about the
default value.

matz.
 
M

Mark Hubbart

"w" == walter <[email protected]> writes:

w> results = Hash.new{|h,k| h[k] = 0}

[...]

w> expected = {}

your 2 Hash are not the same : they don't use the same default value


Guy Decoux

Thanks for the response Guy,


I changed both hashes to be created by Hash.new{|h,k| h[k] = 0} but I
still get the error.....
[...]

for a fairly simple workaround, try this line instead:

assert_equal(expected.sort, @shipTo1.word_counts.sort)

it will convert the hashes to an array, sort them the same way, and
compare them.

cheers,
--Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top