If you're looking for composability and flexibility, this version will

  1. accept either a list of hashref;
  2. return a list or hashref in context;
  3. provides key and value as: $a & $b; and in @_; and the value as $_.

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.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

In reply to Re^7: map and grep (but for hashes) by BrowserUk
in thread map and grep (but for hashes) by zerohero

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.