Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Hash filter one-liner not working as expected

by nysus (Vicar)
on Mar 17, 2019 at 10:09 UTC ( #1231351=perlquestion: print w/replies, xml ) Need Help??

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

I'm not sure why this isn't working. I got a hash that looks like this:

$hash= { 'test_link_color' => '#31e500', 'test_widget_header_color' => '#c6b989', 'header_textcolor' => 'blank', 'test_menu_color' => '#004d59', 'test_widget_color' => '#eee3b7', 'custom_logo' => 5, 'test_headline_color' => '#7b0706', 'custom_css_post_id' => -1, 'header_image_data' => bless( { 'height' => 250, 'width' => 1140, 'attachment_id' => 9, }, 'PHP::Serialization::Object +::stdClass' ), 'test_article_background_color' => '#ceddd2', 'test_menu_text_color' => '#ffffff', 'test_widget_title_color' => '#ffffff', 'test_menu_hl_color' => '#a74d3d', 'nav_menu_locations' => { 'menu-1' => 2 }, 'background_color' => 'ffffff', 'test_text_color' => '#000000' };

I want to filter out all keys that aren't a color property, so I have:

my %colors = map { $_ => %$hash{$_} } grep { $_ =~ /color$/ } keys %$h +ash;

I'm getting a result with they key/values all mixed up:

%colors = ( 'ffffff' => 'test_text_color', 'test_article_background_color' => 'test_article_background_ +color', 'blank' => 'test_menu_color', 'test_menu_text_color' => '#ffffff', 'test_text_color' => '#000000', 'background_color' => 'background_color', '#31e500' => 'test_widget_header_color', 'test_widget_title_color' => 'test_widget_title_color', '#eee3b7' => 'test_headline_color', '#ceddd2' => 'test_menu_text_color', 'test_menu_hl_color' => '#a74d3d', '#ffffff' => 'test_menu_hl_color', 'test_link_color' => 'test_link_color', 'test_widget_header_color' => '#c6b989', 'test_widget_color' => 'test_widget_color', 'test_headline_color' => '#7b0706', 'header_textcolor' => 'header_textcolor', 'test_menu_color' => '#004d59' );

I'm not sure what I'm missing here.

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Hash filter one-liner not working as expected
by Laurent_R (Canon) on Mar 17, 2019 at 10:36 UTC
    Hi nysus,

    I'm surprised you don't get an error, as I am getting this with your code:

    syntax error at colors.pl line 31, near "$hash{"

    Anyway, changing your code line with the grep and map as follows:

    my %colors = map { $_ => $hash->{$_} } grep { $_ =~ /color$/ } keys %$ +hash;
    or like this:
    my %colors = map { $_ => $$hash{$_} } grep { $_ =~ /color$/ } keys %$h +ash;
    works for me. Your error seems to be in this: %$hash{$_} (in the map).

    Output of Data::Dumper on the %colors hash:

    $ perl colors.pl $VAR1 = { 'test_menu_hl_color' => '#a74d3d', 'test_widget_color' => '#eee3b7', 'test_text_color' => '#000000', 'test_widget_header_color' => '#c6b989', 'test_menu_color' => '#004d59', 'background_color' => 'ffffff', 'test_article_background_color' => '#ceddd2', 'test_widget_title_color' => '#ffffff', 'test_menu_text_color' => '#ffffff', 'test_link_color' => '#31e500', 'test_headline_color' => '#7b0706', 'header_textcolor' => 'blank' };

      Yup, spotted my problem right after you posted. A brain fart that cost me 25 min of my life. Thanks.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

        A brain fart that cost me 25 min of my life.
        And 10 of mine. ;-) But it was a pleasure to solve the problem, so I really can't complain about it. I like to solve problems far more than, say, playing a game on my computer.
Re: Hash filter one-liner not working as expected
by Dallaylaen (Hermit) on Mar 17, 2019 at 18:06 UTC

    I wonder if there's a hash filter function somewhere, as in:

    my $new_ref = filter_hash { $a =~ /color/ and !ref $b } $hashref;

    Where $a is each key and $b is the corresponding value. Seems trivial to write, so it must exist.

    UPD: Here: Hash::MostUtils - called hashgrep.

Re: Hash filter one-liner not working as expected
by nysus (Vicar) on Mar 17, 2019 at 10:38 UTC

    Doh! I didn't have the proper syntax. Forgot I was dealing with a hash reference in the map function. This works:

    my %colors = map { $_ => $hash->{$_} } grep { $_ =~ /color$/ } keys %$ +hash;

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

      You had syntax for something else. If number of hash elements was odd, Perl would have warned you sooner than you loose 25 minutes, it was simply bad fortune. Btw, it could be:

      my %colors = %$hash{ grep /color$/, keys %$hash };

      with use 5.020; to warn would-be users.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1231351]
Approved by Laurent_R
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2019-06-24 19:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Is there a future for codeless software?



    Results (99 votes). Check out past polls.

    Notices?