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

Dear Monks,

In my following script, the first print statement prints the values of $fvalues correctly, while the second one does not, please let me know how to print the $fvalues out side while loop.

#!/usr/bin/perl open(IN, '<', "cont.fil"); my %fvalues; while(<IN>){ if (/(.*) (.*)/){ $fvalues{$2} = $1; print "$fvalues{$2}\n"; # this one prints } } for($counter = 0 ; $counter < 10 ; $counter++){ print "$fvalues{$counter}" ; # no output } close(IN);
cont.fil contains:

58-OA-A0125 1 58-OA-A0244 2 58-OA-A0264 3 58-ST-A0112 4 58-ST-A0179 5

Replies are listed 'Best First'.
Re: printing array values
by blazar (Canon) on May 19, 2005 at 08:40 UTC
    Please note that you are not having a problem with "printing array values". What you're having to do with is not an array, but an associative array aka "hash" (because they're internally implemented by means of hash tables).
    print $fvalues{$_}, "\n" for keys %fvalues;

    Update: incidentally, while there may be some corner cases in which C-style for loops would result to be convenient, most often perl-style ones cover the vast majority of cases and are most advantageous.

    Update2: oh, and now that I think of it, while the above is more similar to what you were doing in that it iterates over the keys,

    print $_, "\n" for values %fvalues;
    is conceptually simpler. But then it may be more convenient to (locally) set ($\,$,) suitably and directly write
    print values %fvalues;
    Of course if you want to have output sorted according to the keys (as per holli's suggestion at Re^2: printing array values) or something similar, then you have to use keys.
      <nitpick>

      I would prefer the output to be numerically sorted.
      print $fvalues{$_}, "\n" for sort { $a<=>$b } keys %fvalues;
      </nitpick>


      holli, /regexed monk/
      thanks for your reply

      then could you please let me know how i can retreive a particular value from that hash, say for e.g fvalues{3}

        The problem is that there may not be a such a thing as $fvalue{3}. More precisely, hashes are not indexed by numbers, but by keys (strings).

        You may want to store your values in a real array. But then you should discard the keys. Or else you may want an array of arrays (AoA), each of which containing the key and the value. Or a HoA or an AoH. Who knows?!?

        You may also want to push your keys into an array for "sequential" retrieving. But then again, who knows?!? All this smells byzantine and suggests you may have an "XY problem": you are asking X, but you really want to do Y.

        I ask you to trust me when I tell you that this is "very" x 10 basic perl. I recommend reading some basic {introduction,tutorial}...

Re: printing array values
by ZlR (Chaplain) on May 19, 2005 at 08:54 UTC
    Hello,

    It's a hash so as blazar says you would be better off with values

    Still, the for loop does output the values.
    It does so along with some "use of uninitialized value" warnings, corresponding to the values 0, 6, 7, 8, 9 of $counter which are not valid keys in your example . (tested with perl 5.6)

      It does so along with some "use of uninitialized value" warnings, corresponding to the values 0, 6, 7, 8, 9 of $counter which are not valid keys in your example . (tested with perl 5.6)
      Well, it would, had he included this line in his script:
      use warnings;
      Indeed this, and
      use strict;
      are the most important lines in most perl scripts!
Re: printing array values
by japhy (Canon) on May 19, 2005 at 12:56 UTC
    The program appears to work for other users, so I'm guessing your file has extra characters (perhaps a space, perhaps a carriage return) at the end of the lines. This is causing a problem for you, because you're using the file like so: /(.*) (.*)/. That means "zero or more characters, then a space, then zero or more characters". If your line is "ABCDEF 1 " (notice the space at the end), then $1 is "ABCDEF 1" and $2 is "". If the line is "ABCDEF 1\r" (where \r is a carriage return), then $1 is "ABCDEF" like you'd expect, but $2 is "1\r". Since you never print $2, you can't be sure!

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: printing array values
by Aragorn (Curate) on May 19, 2005 at 09:44 UTC
    You don't explain the context of the problem (what are the pieces of data representing, for example), but assuming that the numbers after the 58-xx-xxxx can be ignored, you get something like this:
    #!/usr/bin/perl use strict; use warnings; open(IN, '<', "cont.fil") or die "Cannot open cont.fil: $!\n"; my @fvalues; # Array, not a hash while(<DATA>) { # Reading values from below __DATA__ s +ection, # change to <IN> for the data file. if (/^(\S+)/) { push @fvalues, $1; } } foreach my $value (@fvalues) { print "$value\n"; } close(IN); __DATA__ 58-OA-A0125 1 58-OA-A0244 2 58-OA-A0264 3 58-ST-A0112 4 58-ST-A0179 5

    Arjen

Re: printing array values
by RatKing (Acolyte) on May 19, 2005 at 12:14 UTC
    Ok, just ran the program over here with out any modifications and it works for me....

    I made a few small ajustments to make it little bit simpler to see whats going on and I used strict and warnings (should always do that).

    Just for your info I am using: perl v5.8.0 built for i386-linux-thread-multi
    #!/usr/local/bin/perl -w use strict; open(IN, '<', "test_file.txt"); my %fvalues; while(<IN>){ if (/(.*) (.*)/){ $fvalues{$2} = $1; print " While : $fvalues{$2}\n"; # this one prints } } for(my $counter = 1 ; $counter < 6 ; $counter++){ print " For : $fvalues{$counter}\n" ; # no output } close(IN);