--X1bOJ3K7DJ5YkBrT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sat, Jul 19, 2003 at 12:20:39PM +0900, John W. Long wrote:
> The problem:

I solved it, being more or less focused on size (but not really a lot)
and when I was about to 'optimize' it I read that size doesn't matter :-)

Well, you can find attached my first take.

Note that I changed a couple things in the test cases when I either
couldn't figure out the semantics or thought there was something wrong.

>   string1, string2  bjectDiff.compare(object1, object2)
>   puts [string1, string2]
>   assert_equal('#<TestObject1:0x1 ... @b", ... @d
", ...>', string1)
", ...>', string1)
>   assert_equal('#<TestObject1:0x2 ... @b, ... @d, ...>', string2)

instance variables are output in lexicographical order

>   complexObject1  estObject1.new('1', {:a 1, :b 2, :j 3}, [1, 2,

you seem to assume that hash keys are sorted before printing (which
isn't always possible, but...)

[I assumed hashes would always be sortable with sort {|a,b|a.to_s <b.to_s}
 which is not really sensible]

>   puts [string1, string2]
>   assert_equal('#<TestObject1:0x3 ... @ba, :b, ...}, @c, ... 3],
> @dTestObject1:0x1 ... @b", ... @d
", ...>, ...>', string1)
", ...>, ...>', string1)
>   assert_equal('#<TestObject1:0x4 ... @ba, :b<TestObject1:0x284a3a8
> @c
", @b ", @el, @a
", @d ">, ...}, @c, ...], but iv are not here?? (You're using #inspect instead of a recursive call to object_to_s) [I corrected that to have the same format as "top level" object_to_s] > assert_equal('[... 2, 3, ... ...]', string_a) > assert_equal('[... 3, 4, ... ... 6]', string_b) In arrays, '...' is used for the first element if equal to that othe other array [kept that] > assert_equal('{:a, :b, ... :d}', string_a) > assert_equal('{ :b, ... :d, :j}', string_b) ... which is not the case for hashes: spaces instead??? [changed to use '...' instead, as in arrays] And again, these semantics won't always work. What happens if you have keys from different classes, how do you get a meaningful order there? Perhaps sorting by class name? My solution + the test case modifications are attached. It only passes the tests, there's a couple more things that need to be done for general use (just adding a couple 'when' clauses for other literals). -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com "Who is General Failure and why is he reading my hard disk?" Microsoft spel chekar vor sail, worgs grate !! -- Felix von Leitner, leitner / inf.fu-berlin.de --X1bOJ3K7DJ5YkBrT Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="objectdiff.rb" require 'test/unit' class TestObject1 attr_accessor :a, :b, :c, :d, :e def initialize(a, b, c, d, e il) @a, @b, @c, @d, @e , b, c, d, e end end class TestObject2 attr_accessor :a, :b, :c, :d, :f, :g def initialize(a, b, c, d, f, g) @a, @b, @c, @d, @f, @g , b, c, d, f, g end end class ObjectDiff class << self def compare(o1, o2) compare_same_class(o1, o2) end def compare_same_class(o1, o2) return object_to_s(o1, o2), object_to_s(o2, o1) end def compare_array(a1, a2) return object_to_s(a1, a2), object_to_s(a2, a1) end def compare_hash(h1, h2) return object_to_s(h1, h2), object_to_s(h2, h1) end def object_to_s(obj, other il) case obj when NilClass return 'nil' when Fixnum return obj.inspect when String return obj.inspect when Array return obj.inspect unless Array other r [" obj.each_with_index do |o,i| if i < other.size && o other[i] r << (i 0? '': ' ') + "..." elsif i < other.size r << (i 0? '': ' ') + object_to_s(o, other[i]) r << ',' unless i obj.size - 1 else r << (i 0? '': ' ') + object_to_s(o) r << ',' unless i obj.size - 1 end end return r << "]" when Hash keys bj.keys.sort{|a,b| a.to_s <b.to_s} r {" keys.each_with_index do |k, i| if Hash other and other.key?(k) and obj[k] other[k] r << (i 0? '': ' ') + "..." elsif Hash other and other.key?(k) r << (i 0? '': ' ') + k.inspect + " + object_to_s(obj[k], other[k]) r << ',' unless i keys.size - 1 else r << (i 0? '': ' ') + k.inspect + " + object_to_s(obj[k]) r << ',' unless i keys.size - 1 end end return r << '}' end r #<#{obj.class}:0x%x" % obj.__id__ vars bj.instance_variables vars.sort.each_with_index do |iv, i| if !other || !other.instance_variables.include?(iv) || other.instance_eval(iv) !bj.instance_eval(iv) if other && other.instance_variables.include?(iv) r << " #{iv}<< object_to_s(obj.instance_eval(iv), other.instance_eval(iv)) else r << " #{iv}<< object_to_s(obj.instance_eval(iv)) end r << "," unless i vars.size - 1 elsif other r << " ..." end end r << ">" end end end class TC_ObjectDiff < Test::Unit::TestCase def test_to_s object estObject1.new('a', 'b', 'c', 'd', [1, 2, 3, 4]) def object.__id__ 0 end assert_equal('#<TestObject1:0x0 @a ", @b ", @c
", @d ", @e, 2, 3, 4]>', ObjectDiff.object_to_s(object)) end def test_compare object1 estObject1.new('a', 'b', 'c', 'd') def object1.__id__ 1 end object2 estObject1.new('a', '', 'c', '') def object2.__id__ 2 end string1, string2 bjectDiff.compare(object1, object2) puts [string1, string2] assert_equal('#<TestObject1:0x1 ... @b ", ... @d ", ...>', string1) assert_equal('#<TestObject1:0x2 ... @b, ... @d, ...>', string2) complexObject1 estObject1.new('1', {:a 1, :b 2, :j 3}, [1, 2, 3], object1) def complexObject1.__id__ 3 end complexObject2 estObject1.new('1', {:a 2, :b object1, :j 3}, [0, 2], object2) def complexObject2.__id__ 4 end string1, string2 bjectDiff.compare(complexObject1, complexObject2) puts [string1, string2] assert_equal('#<TestObject1:0x3 ... @ba, :b, ...}, @c, ... 3], @dTestObject1:0x1 ... @b ", ... @d ", ...>, ...>', string1) assert_equal('#<TestObject1:0x4 ... @ba, :b<TestObject1:0x1 @a ", @b ", @c
", @d ", @el>, ...}, @c, ...], @dTestObject1:0x2 ... @b, ... @d, ...>, ...>', string2) end def test_compare_different_classes object1 estObject1.new('a', 'b', 'c', 'd') def object1.__id__ 5 end object2 estObject2.new('a', '', 'c', '', 'f', 'g') def object2.__id__ 6 end string1, string2 bjectDiff.compare(object1, object2) puts [string1, string2] assert_equal('#<TestObject1:0x5 ... @b ", ... @d ", @el>', string1) assert_equal('#<TestObject2:0x6 ... @b, ... @d, @f", @g">', string2) end def test_compare_array a 1, 2, 3, 4, 5] b 1, 3, 4, 4, 5, 6] string_a, string_b bjectDiff.compare_array(a, b) puts [string_a, string_b] assert_equal('[... 2, 3, ... ...]', string_a) assert_equal('[... 3, 4, ... ... 6]', string_b) end def test_compare_hash a :a 1, :b 2, :c 3, :d 4 } b :j 2, :b 3, :c 3, :d 5 } string_a, string_b bjectDiff.compare_hash(a, b) puts [string_a, string_b] assert_equal('{:a, :b, ... :d}', string_a) assert_equal('{:b, ... :d, :j}', string_b) end end --X1bOJ3K7DJ5YkBrT--