http://www.perlmonks.org?node_id=459398

Recursively traverses two data structures and tests for match. Takes any data type; arrays and hashes must be passed by reference. Returns false if two arrays have the same items in a different order. Streamlined for speed with large numbers of data items.

EDIT: Edited to test CODE refs.

use strict; use warnings; sub match { return ($_[0] eq $_[1] ? 1 : 0) if ! ref $_[0] && ! ref $_[1]; my ($x, $y, $i) = @_; return 0 if ref $x ne ref $y; if (ref $x eq 'ARRAY') { return 0 if $#$x != $#$y; for ($i = 0; $i <= $#$x; $i++) { return 0 if ! match($x->[$i], $y->[$i]); } return 1; } if (ref $x eq 'HASH') { return 0 if scalar keys %$x != scalar keys %$y; my @x = sort keys %$x; my @y = sort keys %$y; for ($i = 0; $i <= $#x; $i++) { return 0 if $x[$i] ne $y[$i]; } for ($i = 0; $i <= $#x; $i++) { return 0 if ! match($x->{$x[$i]}, $y->{$y[$i]}); } return 1; } return ($x eq $y ? 1 : 0); }

Replies are listed 'Best First'.
Re: Recursively traverse two data structures and test for match
by diotalevi (Canon) on May 23, 2005 at 01:32 UTC
    Neither this nor Test::More's is_deeply correctly handle overloaded values.
      That's not a slam on anything that uses overloaded values. There's just a problem with how overloading is done. I wrote about it here. There's just no correct way to compare overloaded values from different classes.

      • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
      • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
        You didn't understand. If you wished to compare that two structures were identical as if overloading didn't exist, you're out of luck. Test::More's is_deeply doesn't do anything to disable the overloading and to thus act on the data structure transparently.
Re: Recursively traverse two data structures and test for match
by dragonchild (Archbishop) on May 23, 2005 at 01:09 UTC
    What does this provide over Test::More's is_deeply()?

    • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
    • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
Re: Recursively traverse two data structures and test for match
by TedPride (Priest) on May 23, 2005 at 17:39 UTC
    I imagine the routine doesn't provide anything over Test::More, but I thought it would be fun to roll one on my own. Besides, you can just cut and paste this routine into your program - no need to mess with installing modules.

    I notice I didn't include tests for CODE refs, however. I'm a naughty boy.

      I didn't see you testing for cycles. Any self referential structure is going to cause your code to stop in an infinite loop.