in reply to get solution as short as possible

A map with a ternary that returns () in one case is usually a good place for a grep:

for (grep /^default_option_/, keys %def) { my (undef, $option) = split /_/, $_, 2; $s{$option} = $def{$_}; }

(untested).

Update: Another approach without an explicit loop, but with map/grep:

my @keys = grep /^default_option_/, keys %def; my @short_keys = map +(split /_/, $_, 2)[1], @keys; @s{@short_keys} = @def{@keys};

Regarding your wish to shorten the code, I can recommend The path to mastery.

Replies are listed 'Best First'.
Re^2: get solution as short as possible
by throop (Chaplain) on Aug 17, 2011 at 15:23 UTC
    I really, really like your 3-line solution; especially the final line. I'm using that idiom in some coding right now. Thanks!
Re^2: get solution as short as possible
by Anonymous Monk on Aug 17, 2011 at 11:34 UTC
    for (grep /^default_option_/, keys %def) { my (undef, $option) = split /_/, $_, 2; $s{$option} = $def{$_}; }

    ... changes to a somewhat dense form of ...

    for ( grep /^default_option_/, keys %def ) { $s{ (split /_/, $_, 2)[-1] } = $def{ $_ }; }

    ... put other way (by way of moritz's explicit hint) ...

    %s = map { (split /_/, $_, 2)[-1] => $def{ $_ } } # Useless use of grep. grep /^default_option_/, keys %def ;

    ... which begs to go to the original version despite OP's request...

    %s = map { m/^ default_ (option_.+) $/x ? ( $1 => $def{ $_ } ) : () } keys %def ;

    I, myself, would not have bothered with any of map-grep or for-grep versions shown thus far. In case of for-loop, I would be prone to write "next if".

      second version avoids double using "default_option_" string but, in my opinion, is less straightforward than my original.

      Compare
      for ( grep /^default_option_/, keys %def ) { $s{ (split /_/, $_, 2)[-1] } = $def{ $_ }; }
      with original
      foreach (map { /^default_option_(.*)/ ? $1 : () } keys %def) { $s{"option_$_"} = $def{"default_option_$_"}; }
      Second case more distinctly highlights idea to use the subpart of key string as a new key. I wished to have something like
      for (grep /^default_option_(.*)/, keys %def) { $s{"option_$1"} = $def{$_}; }
      or even more short
      $s{"option_$1"} = $def{$_} for (grep /^default_option_(.*)/, keys %def +);

      Of course the last 2 solutions are incorrect. But if some monk knows how to achieve such level of laconism and clearness in one that would be a great pattern.

      Anyway I like your solutions for custom, rare cases. But I need a nice looking, straightforward and short version for everyday use. Of course if it exists in Perl 5 universe.

      Another problem is that your last solution truncates hash if it has data. It's not appropriate for me. Though I'm not sure if moritz's version does this.

      FYI: I've just registered. And this is my post

        A(...) problem is that your last solution truncates hash if it has data. It's not appropriate for me. Though I'm not sure if moritz's version does this.

        If you are objecting to destruction of %s, then mortiz's version does preserve the previous elements.

        As there is no getting around search for interesting keys and generation of second key list, so just use ...

        sub simple_fill { my ( $save , %def ) = @_; for ( keys %def ) { my ( $opt ) = ( $_ =~ m/^ default_ (option_.+) $/x ) or next; $save->{ $opt } = $def{ $_ }; } return; }

        And then there is use of map|grep in void context for side effects, which some may not regard as "a nice looking, straightforward (...) version for everyday use".