Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Probably an easy map question

by cosmicperl (Chaplain)
on Jan 15, 2009 at 01:56 UTC ( [id://736434]=perlquestion: print w/replies, xml ) Need Help??

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

Hi All,
  I hardly ever use map, I'm forcing myself to use it when dealing with whole arrays (when I only want to looking for something in an array I'll use foreach and last). Already I'm struggling to figure out how to do something I'm sure is quite simple.

I have a file with a list of keys and values separated by =. Such as:-
key1 = value1 key2 = value2
I want to read this into a hash. How do I do it with map?

One of my feeble attempts:-
open( INF, 'file' ); %hash = map { my ( $a, $b) = split( / = /, chomp($_) ); $a => $b } + <INF>;; close( INF );
I'm sure with a little help, and if I keep bashing my head against the wall using map for these kinds of situations will finally sink in.

Lyle

Replies are listed 'Best First'.
Re: Probably an easy map question
by shmem (Chancellor) on Jan 15, 2009 at 02:01 UTC

    Your usage of map is fine - but it isn't for chomp.

    %hash = map { chomp; my ( $a, $b) = split / = /; $a => $b } <INF>;

    should do. update: note that $_ is implicit for chomp and split.

      I don't think you need $a and $b, split should do the job by itself:

      my %hash = map {chomp; split / = /} <INT>;
      all the best, andye

        I shouldn't use ($a, $b) since these are special and for something else - but I adhered to the OP's code in order to not change too much... ;-)

Re: Probably an easy map question
by kyle (Abbot) on Jan 15, 2009 at 02:21 UTC

    You could forget the chomp and split and do it with a regexp.

    use Data::Dumper; my %h = map { /^([^=]+?)\s*=\s*(\S.*)/ } <DATA>; print Dumper \%h; __DATA__ a = fred b = 1 ignorethis c = ===

    Output:

    $VAR1 = { 'c' => '===', 'a' => 'fred', 'b' => '1' };

    This works because the regexp evaluates to a list of the contents of the two captures. What's nice about this is that it elegantly handles values that have an equal sign in them. It also just plain skips over any line that doesn't fit the format.

      Am I correct in thinking that this operates on DATA in slurp mode (i.e. reading all the lines in at once)? Or does this work like while (<X>) magic?

      for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";

        Yes, it will read the entire input before doing any work. That's true of the OP too, and the other map-based solutions I see posted.

Re: Probably an easy map question
by Lawliet (Curate) on Jan 15, 2009 at 02:10 UTC

    I believe you are having a problem with chomp(). That being said, read up on chomp and modify your codez.

    my %hash = map { chomp(my ($a, $b) = split(/ = /, $_)); $a => $b } @ar +ray;

    (Hint, lookup what chomp returns.)

    Update: shmen beat me to it :(. I like the way he chomped, too -- better looking than those parens (in this scenario, anyway).

    Update: Reworded my previous update.

    And you didn't even know bears could type.

Re: Probably an easy map question
by jdporter (Paladin) on Jan 15, 2009 at 02:52 UTC
    my %h = do { local( @ARGV, $/ ) = ($file); <> =~ /^(.*?) = (.*)/gm };

      The "$" is useless.

      In the spirit of the OP, here's a (shorter!) variation that uses map:

      my %h = do { local @ARGV = $file; map /^(.*?) = (.*)/, <> };

      One should probably localize $^I when localizing @ARGV.

Re: Probably an easy map question
by bcrowell2 (Friar) on Jan 15, 2009 at 02:19 UTC
    This isn't really an answer to your question, but you might want to think about storing this file in JSON format. Advantages: (1) you don't have to write a parser, just "use JSON;" and (2) if your data structure gets more complex in the future (which is likely), you can adapt more gracefully.
Re: Probably an easy map question
by JavaFan (Canon) on Jan 15, 2009 at 11:01 UTC
    I hardly ever use map, I'm forcing myself to use it when dealing with whole arrays
    This sounds you rather don't use map. That's fine. Perl allows you do things in more than one way, and avoiding map seldomly leads to complicated code.

    Instead of forcing yourself to use map, you may be better off to not use it at all.

      Forcing yourself to use a feature you normally avoid is a good way to learn about it, and that can't be bad. If nothing else... it'll help prepare you for when you need to maintain someone else's code.

      Between the mind which plans and the hands which build, there must be a mediator... and this mediator must be the heart.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-03-28 13:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found