shemp has asked for the wisdom of the Perl Monks concerning the following question:

I just wrote a bit of code to compare 2 'trees', where a tree is a hashref of hashrefs or hashrefs ...
The code is general in that it will deal with arbitrary depth trees, but it seems like i did more work than i needed to, so im looking for better solutions.
The comparison is following every path down 1 tree, and seeing if that path exists in the other tree. If not, report the entire path that wasnt in the second tree. The path is reported as an arrayref of the keys down the path. So the function returns an arrayref of the path arrayrefs that are in the first tree but not the second.
Anyway, heres the code, any comments would be appreciated:

Update:
modified the return in the else of expand_trees_to_arrays()
Because i realized i had 1 thing wrong in the problem specification, i.e. the values in the nodes are irrelevant to what i am looking for, so i dont want any reporting done there, i only want to compare the paths down to the nodes. Sorry for the change
sub compare_hashtrees { my ($tree_1, $tree_2) = @_; my @tree_1_only; foreach my $tree_1_key (keys %$tree_1) { my $sub_arrays_not_in_tree2 = []; if ( ! exists $tree_2->{$tree_1_key} ) { # the subtree is missing from tree_2 - expand it $sub_arrays_not_in_tree2 = expand_tree_to_arrays($tree_1->{$tree_1_key}); } elsif ( ref $tree_1->{$tree_1_key} ) { # another level of hashing $sub_arrays_not_in_tree2 = compare_hashtrees($tree_1->{$tree_1_key}, $tree_ +2->{$tree_1_key}); } foreach my $sub_array (@$sub_arrays_not_in_tree2) { push @tree_1_only, [$tree_1_key, @$sub_array]; } } return \@tree_1_only; } sub expand_tree_to_arrays { my ($tree) = @_; if ( ref $tree ) { my @expanded; foreach my $key (sort keys %$tree) { my $sub_expanded = expand_tree_to_arrays($tree->{$key}); foreach my $path (@$sub_expanded) { push @expanded, [$key, @$path]; } } return \@expanded; } else { # return [ [$tree] ]; # its a scalar return [ [ ] ]; } }

Replies are listed 'Best First'.
Re: Tree comparisons
by dragonchild (Archbishop) on Jun 23, 2004 at 01:29 UTC
    Several of the Test::* modules have a cmp_deeply() type function. You might want to consider using that code as a starting point.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: Tree comparisons
by jZed (Prior) on Jun 22, 2004 at 22:04 UTC
    For quick and dirty:
    use Data::Dumper; print "same" if Dumper($hashref1) eq Dumper($hashref2);
    :-)
      I really need the specific differences - in a structure similar to what im returning. This is part of a big data crunching system that cleans up government public record data.
        I wonder if doing the simple Dumper comparison first and only doing your bit if the first fails might save time?