in reply to Re^6: map and grep (but for hashes)
in thread map and grep (but for hashes)
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.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^8: map and grep (but for hashes)
by zerohero (Monk) on Feb 02, 2009 at 17:57 UTC |