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

Hi All,

I have an arbitrarily complex data structure, and I'd like to change the values in all the hashrefs in it when the corresponding key matches a certain pattern. The boring subroutine below does the trick, but I feel like there must be something existing on CPAN which I haven't been able to find, that handles things like this more generically (and cleanly/efficiently?). Can anyone point me towards such a module? Thanks
sub change_hash_values { my $sub = shift; my $h = shift; my $match = shift; return unless ref($h); for ( ref($h) ) { /HASH/ and do { for ( keys %$h ){ change_hash_values ( $sub, $h->{$_}, $match ); $h->{$_} = $sub->( $h->{$_} ) if /$match/; } }; /ARRAY/ and do { change_hash_values ( $sub, $_, $match ) for @$h; }; } } my $z = { foo => [qw(a b c)], bar => [ 'a' , { changeme => 'oz' } ], baz => 'z' }; change_hash_values( sub { $_[0]=~s/z/x/g; return $_[0]; },$z, qr/chang +e/); # Turns oz into ox

Replies are listed 'Best First'.
Re: DataStructure::RecursivelyTransform?
by BrowserUk (Patriarch) on May 02, 2006 at 17:05 UTC

    Take a look at Data::Rmap. Something like this should do the trick.

    use Data::Rmap qw[ rmap_hash ]; rmap_hash{ for my $key ( keys %{ $_ } ) { next unless $key eq 'Target key value'; $_->{ $key } =~ $someRegex; } } $refToArbitraryStructure;

    Whether that is an easier than what you have is your decision. More efficient? Benchmark it :)


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.