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

I have use for a system involving an (untied) hash which is used as a base for adding comments to a developing system. As the system is developed, a new hash is created, and I need to have my base hash updated to take in new entries, still retaining the comments previously added, but deleting entries which are made obsolete in the new hash. I can do a kind of update merge thus:
my %newbase = ( %oldhash, %newhash );
but this leaves the problem of keys or branches of the hash tree which were in hash1, but are not in hash 2, and should be eliminated from hash3 if it's to be the new base hash. My first draft solution relies on a recursive traversal of two hashes. This seems to work ( note: It has a few debugging stubs in it while I keep chewing it over). But is there MTOWTDI, and it there one simpler and/or less stack-intensive ? I'm using:
sub prunecheck { my ( $var1, $var2 ) = @_; my @var2keys = (); @var2keys = ( keys %$var2 ) if(ref($var2)=~ /HASH/); return unless defined $var1; for ( ref($var1) ) { if (/HASH/) { if ( !(@var2keys) ) { $$var1 = (); } else { for my $key1( keys %$var1 ) { if ( !exists( $$var2{$key1} ) ) { delete( $$var1{$key1} ); } else { # print "\t$key1\n"; prunecheck( $var1->{$key1}, $var2->{$key1} ); } } } } elsif (/ARRAY/) { foreach (@$var1) { prunecheck( $_, $var2 ) ; } } else { # print "\t\t$var1\n"; } } } prunecheck(\%newbase, \%newhash);
Appreciate comments, suggestions. Sneaking feeling I'm missing something obvious -- and simpler.

Replies are listed 'Best First'.
Re: Updating one hash from another and pruning
by Abigail-II (Bishop) on Aug 13, 2002 at 15:04 UTC
    I'm not going to try to figure out what prunecheck is doing, it's certainly doing more than you describe (it's recursive, on doing different things based on the argument types).

    But looking at the problem you describe, don't you want something like:

    %hash3 = %hash1; @hash3 {grep {exists $hash2 {$_}} keys %hash1} = @hash2 {grep {exists $hash2 {$_}} keys %hash2};
    If not, then I don't understand what you want.


      > ....it's certainly doing more than you describe Well, yes, it has stubs to print out the details of the final hash -- down to the base (scalar) level. Incidentally, I +think+ it has a problem at the ARRAY level -- don't think it necessarily handles arrays of hashrefs (cf arrays of scalars)... Re: the grep combination -- doesn't it assume you only have one level of hash keys ? -- and so doesn't allow generalizations to the multidimensional hash of hashes level? An advantage of the recursive traversal is that it's designed to descend through all levels...