Re: Need a test for deep equality
by Corion (Patriarch) on Apr 20, 2002 at 10:59 UTC
|
While implementing my module File::Modified (nee File::Dependencies - not yet on CPAN), I also wanted such a deep comparision method, but I didn't find one either (in Python, this would be as easy as struct_a == struct_b :-)). But I would prefer basing the thing on Data::Dumper or another existing wheel, as cyclic structures are a nasty thing to handle. On the problem of hash order, it would make sense to do a sort() on the keys of the hashes before writing them out, so that identical hashes produce identical strings - maybe that would be just a small patch to Data::Dumper.
Update : Of course, somebody already invented this wheel, in Test::More by Michael Schwern. There is the routine is_deeply, which does a deep compare - maybe this would warrant extraction in its own module...
perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The
$d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider
($c = $d->accept())->get_request(); $c->send_response( new #in the
HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
| [reply] [d/l] |
|
maybe that would be just a small patch to Data::Dumper.
Perhaps, but somehow I doubt it'll happen. First off you would have to do it twice, once in C and once in perl. Second off Data::Dumper is optimized for speed and the overhead of sorting, especially a tied structure, could get prohibitive. OTOH Data::BFDump does sort its keys, and IIRC so does Data::Dump.
Yves / DeMerphq
---
Writing a good benchmark isnt as easy as it might look.
| [reply] |
Re: Need a test for deep equality
by andreychek (Parson) on Apr 20, 2002 at 15:43 UTC
|
There is a module for this over at CPAN called Struct::Compare. From the description:
Compares two values of any type and structure and returns true if they are the same. It does a deep comparison of the structures, so a hash of a hash of a whatever will be compared correctly.
So, you just pass in two structures, and it returns true or false, based on whether or not the structures are equal.
Hope that helps!
-Eric | [reply] |
Re: Need a test for deep equality
by gav^ (Curate) on Apr 20, 2002 at 21:52 UTC
|
use Data::Compare;
my $hr1 = {a=>'foo',b=>'bar'};
my $hr2 = {b=>'bar',a=>'foo'};
print "They are ", (Compare($hr1,$hr2) ? "the same" : "different"), "\
+n";
gav^ | [reply] [d/l] |
Re: Need a test for deep equality
by Dog and Pony (Priest) on Apr 20, 2002 at 11:08 UTC
|
Maybe this isn't possible, but you could use something like Tie::IxHash to have the hashes always return the same order of keys.
Otherwise, perlfaq4 has examples on how to do this using FreezeThaw.
Maybe one of these might be what you need.
You have moved into a dark place.
It is pitch black. You are likely to be eaten by a grue. | [reply] |
Re: Need a test for deep equality
by rinceWind (Monsignor) on Apr 21, 2002 at 09:49 UTC
|
Update: What I didn't specify, but perhaps should have, is that parts of the data structure are blessed object references, and I want to compare the guts of the objects.
Conclusion:
Conclusion: either fix Data::Dumper or roll my own compare routine :-<.
Update 2: I have been looking further at Test::More. There are numerous versions floating about, owing to the way in which people have used it to package up their tests in their own modules.
The definitive Test::More on CPAN has a function eq_hash, which suffers from the same syndrome as Data::Dumper when it comes to ordering of keys.
Update 3: simonm++ The module Class::MakeMethods::Utility::Ref does the business!
Shame about the name - something as useful should not IMO have a module name 4 levels down, with no clue as to what it can do. | [reply] |
|
I have to wonder if you could canoncalize the hashes. A simple "alphabetize the keys at each level" comes to mind. This could be expensive for large/deep hashes, but, it may be worth it to you.
| [reply] |
|
This is an old thread, which is probably the reason for this omission, but... Test::More has an is_deeply() that works for my purposes (no object references). The docs for Test::More also recommend other Perl modules that will handle object references, etc.
| [reply] |
Re: Need a test for deep equality
by thraxil (Prior) on Apr 20, 2002 at 17:55 UTC
|
| [reply] |
Re: Need a test for deep equality
by ides (Deacon) on Apr 21, 2002 at 22:26 UTC
|
Maybe I am missing something here but is there a reason
you just don't compare the hashes by hand? Using recursion
if they are hashes of hashes,etc?
Something along these lines?
my %hash1 = { 'foo' => 1, 'bar' => 1 };
my %hash2 = { 'foo' => 1, 'bar' => 1 };
foreach my $key ( keys(%hash1) ) {
die "Not equal" if $hash1{$key} != $hash2{$key};
}
I think you may be making this harder than it needs to be,
either that or I'm not understanding your problem fully.
-----------------------------------
Frank Wiles <frank@wiles.org>
http://frank.wiles.org
| [reply] [d/l] |
Re: Need a test for deep equality
by willijar (Initiate) on Apr 22, 2002 at 12:03 UTC
|
While there are many Perl functions that could do this I would recommend rolling your own specific to your application. It isn't really reinventing the wheel as every application and structure will probably require a different definition for equality. For example are two structures equal only if stored at the same location or if they contain the same data. WHat about when comparing the object contents. At what depth do yuo compare contents rather than identity. Similarly for vectors. In comparing Strings should they be case insensitive. etc. Can an integer be equal to a float with the same printed representation. It isn't a simple question with simple answers.
| [reply] |
Re: Need a test for deep equality
by simonm (Vicar) on Apr 23, 2002 at 05:00 UTC
|
Yes, I've got a module on CPAN that does this -- see the ref_compare function in Class::MakeMethods::Utility::Ref, based on some old code by David Muir Sharnoff. It should handle scalar values, plain hashes or arrays, or arbitrary nested data structures.
-Simon
| [reply] |
Re: Need a test for deep equality
by KILNA (Acolyte) on May 02, 2002 at 21:21 UTC
|
Another option is Data::Denter as a serializer for comparissons. It supports blessed objects and references, in addition to being able to sort hashes by default. Persoanlly, I think the output is a lot easier on the eyes than trying to look at Dumper output too. If I remember right, it can even handle circular references.
-- KILNA - pop music for cyborgs - http://www.kilna.com | [reply] |