Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

map a hash with a default value or exclude

by kayahk (Initiate)
on Sep 13, 2011 at 00:13 UTC ( #925594=perlquestion: print w/ replies, xml ) Need Help??
kayahk has asked for the wisdom of the Perl Monks concerning the following question:

this has probably been asked multiple times, but i have a config file in the form of:
key=value\n

sometimes value the is missing, is there a way to exclude the key itself or add a default value to the key using map'ing.
this is the simple code i currently have:
sub load_config { my $self = shift; open(my $fh, $self->{config_file}) or croak "open error".$self->{c +onfig}; %{$self->{info}} = map { chomp; split'='; } <$fh>; close($fh); return $self; }
thanks

Comment on map a hash with a default value or exclude
Download Code
Replies are listed 'Best First'.
Re: map a hash with a default value or exclude
by GrandFather (Sage) on Sep 13, 2011 at 01:17 UTC

    map returns a list so the solution to your missing value conundrum is to return an empty list for suppressed values. I'm not sure I'd solve this particular problem using a map and the following technique, but the technique is worth knowing about in any case:

    use strict; use warnings; my %info = map {chomp; my @parts = split '='; @parts == 2 && length $parts[1] ? @parts : () } <DATA>; print "$_: $info{$_}\n" for sort keys %info; __DATA__ key=value nokey=

    Prints:

    key: value
    True laziness is hard work
Re: map a hash with a default value or exclude
by toolic (Bishop) on Sep 13, 2011 at 00:33 UTC
    If you can live with a map-less solution, this excludes keys without values:
    use warnings; use strict; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my %info; while (<DATA>) { chomp; my ($k, $v) = split /=/; $info{$k} = $v if length $v; } print Dumper(\%info); __DATA__ a=5 b=6 c= d=7
    prints:
    $VAR1 = { 'a' => '5', 'b' => '6', 'd' => '7'
    This keeps the key, with a default value:
    while (<DATA>) { chomp; my ($k, $v) = split /=/; $info{$k} = (length $v) ? $v : 666; }
Re: map a hash with a default value or exclude
by kcott (Abbot) on Sep 13, 2011 at 02:59 UTC

    In the spirit of TIMTOWTDI, here's a method that involves capturing your split() output in an arrayref:

    ... map { chomp; [split'=']; } <$fh>;

    which is subsequently filtered through a second map():

    %{$self->{info}} = map { EXPR } map { chomp; [split'=']; } <$fh>;

    To exclude a key, EXPR is:

    defined $_->[1] ? @$_ : ()

    To use a default value (here I've used the string: undef), EXPR is:

    $_->[1] //= q{undef}; @$_

    -- Ken

      or instead of using the ?: in the "decoding" map for the elimination case you could instead use a grep:

      %{$self->{info}} = map {@$_} grep {defined $_->[1]} map {chomp; [split +'='];} <$fh>;

      In any case generating the array ref doesn't actually seem to be a win in terms of succinctness or comprehensibility.

      True laziness is hard work

        Yet another way, using the 3-argument form of split, which guarantees that the input string is split into two parts and no more or less. The second part would be a string of length 0, instead of an undefined value.

        %{$self->{info}} = map {@$_} grep {$_->[1]} map {chomp; [split '=', $_ +, 2];} <$fh>;

        I prefer this form of split in handling key=value type strings, since it handles the cases where a value could have an embedded '=' (PASSWORD=blah=argh!), whereas the shorter one-(or, two-)argument forms would return truncated values.

        Yet another alternative, using only one map:

        %{$self->{info}} = map {chomp; my ($k, $v) = split '=', $_, 2; $v ? ($ +k => $v) : (); } <$fh>;

        If we want to supply default values:

        # assuming default values are in %defaults %{$self->{info}} = map {chomp; my ($k, $v) = split '=', $_, 2; $k => $ +v || $defaults{$k}; } <$fh>;
Re: map a hash with a default value or exclude
by jethro (Monsignor) on Sep 13, 2011 at 01:18 UTC

    Nothing prevents you from inserting code as complex as you need into the map:

    ... = map { chomp; my ($right,$left)= split'='; if ($left) { ($right,$ +left) } else { () } } <$fh>;
Re: map a hash with a default value or exclude
by jwkrahn (Monsignor) on Sep 13, 2011 at 05:02 UTC
    is there a way to exclude the key itself

    %{$self->{info}} = map /^([^=]+)=(.+)$/, <$fh>;

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2015-07-08 00:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (93 votes), past polls