If you're looking for composability and flexibility, this version will
Which allows your composed "query" to operate fairly naturally:
my %new = hmap { exists $b->{ nick } && $b->{ nick } =~ m[^(?:rbush|fred)$] ? ( $a => scalar hgrep{ $a =~ m[^(nick|phone)$] } $b ) : () } \%old;
Code and tests
#! perl -slw use strict; use Carp; use Data::Dump qw[ pp ]; sub hmap (&@) { our( $a, $b ); my $code = shift; croak "Even sized list or hash ref required" if @_ & 1 and not @_ == 1 && ref( $_[0] ) =~ m[HASH]; @_ = %{ $_[0] } if @_ == 1; my @rv; while( @_ ) { local( $a, $b ) = splice( @_, 0, 2 ), my $rv = $code->( $a, local $_ = $b ); push @rv, $rv ? ( $a, $rv ) : (); } wantarray ? @rv : { @rv }; } sub hgrep (&%) { our( $a, $b ); my $code = shift; croak "Even sized list or hash ref required" if @_ & 1 and not @_ == 1 && ref( $_[0] ) =~ m[HASH]; @_ = %{ $_[0] } if @_ == 1; my @rv; while( @_ ) { local( $a, $b ) = splice( @_, 0, 2 ); my $rv = $code->( $a, local $_ = $b); push @rv, $rv ? ( $a, $b ) : (); } wantarray ? @rv : { @rv }; } my %h = ( 'a' .. 'j', 's' .. 'z' ); pp 'start: ', \%h; my %r1 = hmap{ ++$b } %h; pp 'incr values: ', \%r1; my $r2 = hmap{ ++$_ } %r1; pp 'and again: ', $r2; my %h3 = hmap{ ++$_[1] } $r2; pp 'and once more: ', \%h3; my %s = hgrep{ $a le 'm' } %h; pp 'filter keys le m: ', \%s; my $t = hgrep{ length $b > 1 } \%h3; pp 'filter values longer than 1 char: ', $t; print "\n-----------\n"; my %old = ( '1' => { 'nick' => 'rbush', 'bday' => '3/12/1965', 'phone' => '555 +1212' }, '5' => { 'nick' => 'fred', 'bday' => '5/01/1972', 'phone' => '111 +2300' }, '11'=> { 'nick' => 'joan', 'bday' => '1/02/2033', 'phone' => '123 +456789' }, ); my %new = hmap { exists $b->{ nick } && $b->{ nick } =~ m[^(?:rbush|fred)$] ? ( $a => scalar hgrep{ $a =~ m[^(nick|phone)$] } $b ) : () } \%old; pp \%new; __END__ c:\test>hmap ( "start: ", { a => "b", c => "d", e => "f", g => "h", i => "j", "s" => "t", u => + "v", w => "x", "y" => "z" }, ) ( "incr values: ", { a => "c", c => "e", e => "g", g => "i", i => "k", "s" => "u", u => + "w", w => "y", "y" => "aa" }, ) ( "and again: ", { a => "d", c => "f", e => "h", g => "j", i => "l", "s" => "v", u => + "x", w => "z", "y" => "ab" }, ) ( "and once more: ", { a => "e", c => "g", e => "i", g => "k", i => "m", "s" => "w", u => + "y", w => "aa", "y" => "ac" }, ) ( "filter keys le m: ", { a => "b", c => "d", e => "f", g => "h", i => "j" }, ) ( "filter values longer than 1 char: ", { w => "aa", "y" => "ac" }, ) ----------- { 1 => { nick => "rbush", phone => 5551212 }, 5 => { nick => "fred", phone => 1112300 }, }
That done, the next thing you are likely to want, is to be able to process arrays nested in hashes; and hashes nested in arrays; and conditionally either. At which point you are moving into the realms of the provisions of Data::Rmap.
In reply to Re^7: map and grep (but for hashes)
by BrowserUk
in thread map and grep (but for hashes)
by zerohero
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |