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

Save first n values from a file

by Anonymous Monk
on Jan 10, 2014 at 10:13 UTC ( #1070088=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a file with these values,
Name a b c d e f g h
How can i save the first 3 values i.e. (a,b,c) to 3 different variables? i.e.
$i = a $j = b $k = c
Need to repeat till the end of the file, so the next iteration these variable should have values,
$i = d $j = e $ = f

Comment on Save first n values from a file
Select or Download Code
Replies are listed 'Best First'.
Re: Save first n values from a file
by LanX (Canon) on Jan 10, 2014 at 10:40 UTC
    file handles return single lines in scalar context

    while ( my $a =<DATA> ){ my $b=<DATA>; my $c=<DATA>; print $a; } # while ( my $a =<DATA>, my $b=<DATA>, my $c=<DATA> ){ # print $a; # } __DATA__ a b c d e f g h

    please note the difference, the second version will stop after printing "d", since the last group has only 2 entries (i.e. $c is undef)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: Save first n values from a file
by Random_Walk (Parson) on Jan 10, 2014 at 10:33 UTC

    Perhaps a hash, or an array is would suit your purpose better. Here is an example using an array, also showing a way to put the vals in $i, $j, $k and a way to use a hash.

    Update: Added hash demo to code too, and better behaviour when it runs out of values

    use strict; use warnings; my @names; while (my $name = <DATA>) { chomp $name; # remove newline push @names, $name; } print "The third name is $names[2]\n"; my @copy = @names; # take a copy for the hash demo my ($i, $j, $k); while (@names) { for (\$i, \$j, \$k) { if (@names) { $$_ = shift @names; } else { $$_ = 'ran out of records'; # could use undef too } } print "i: $i j:$j k: $k \n"; } # and with a hash my %hash; while (@copy) { %hash = (i=>'', j=>'', k=>''); # clear the hash for my $key (qw(i j k)) { $hash{$key} = shift @copy if @copy; } print "the hash contains $hash{$_} under $_\n" for ('i'..'k'); } __DATA__ a b c d e f g h

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
Re: Save first n values from a file
by johngg (Abbot) on Jan 10, 2014 at 12:09 UTC

    This code builds an AoA by processing three lines at a time and pushing an anonymous array of chomped lines for each group.

    $ perl -Mstrict -Mwarnings -MData::Dumper -e ' sub groupsOf (&$@); open my $inFH, q{<}, \ <<EOD or die $!; a b c d e f g h EOD my @arr; push @arr, groupsOf { chomp @_; [ @_ ] } 3, <$inFH>; sub groupsOf (&$@) { my $rcToRun = shift; my $groupsOf = shift; my $rcDoIt; $rcDoIt = sub { $rcToRun->( map shift, 1 .. ( @_ < $groupsOf ? @_ : $groupsOf ) ), @_ ? &$rcDoIt : (); }; &$rcDoIt; } print Data::Dumper->Dumpxs( [ \ @arr ], [ qw{ *arr } ] );' @arr = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ], [ 'g', 'h' ] ); $

    I hope this is of interest.

    Update: Simpler and assigns to three variables rather than constructing an AoA.

    $ perl -Mstrict -Mwarnings -E ' > open my $inFH, q{<}, \ <<EOD or die $!; > a > b > c > d > e > f > g > h > EOD > > while ( not eof $inFH ) > { > my( $i, $j, $k ) = > map { chomp; $_ } > map { eof $inFH ? () : scalar <$inFH> } > 1 .. 3; > say > q{$i - }, defined $i ? qq{$i; } : q{undef; }, > q{$j - }, defined $j ? qq{$j; } : q{undef; }, > q{$k - }, defined $k ? $k : q{undef}; > }' $i - a; $j - b; $k - c $i - d; $j - e; $k - f $i - g; $j - h; $k - undef $

    Cheers,

    JohnGG

Re: Save first n values from a file
by Lennotoecom (Pilgrim) on Jan 10, 2014 at 12:16 UTC
    this is the dark arts ^ ^,
    but seriously, I think other monks won't approve, still:
    for $x (f .. j){ chomp(${$x} = <DATA>); } print "$f $g $h $i $j\n"; __DATA__ a b c d e
    update*
    addressing the authors exact demands
    here an addition:
    do{for $x (i, g, k){ chomp(${$x} = <DATA>); } print "$i $g $k\n";} until eof; __DATA__ a b c d e f g h
    output:
    a b c d e f g h
      > I think other monks won't approve, still:

      Don't you think, you should at least mention no strict 'refs' ? :)

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        yes, sorry
        just couldn't restrain myself :)
        I hope the readers will understand
Re: Save first n values from a file
by kcott (Abbot) on Jan 12, 2014 at 14:53 UTC

    Here's another way to do it:

    #!/usr/bin/env perl -l use strict; use warnings; my @values; while (<DATA>) { chomp; push @values, $_; if (@values == 3) { process_values(@values); @values = (); } } process_values(@values) if @values; sub process_values { my ($i, $j, $k) = @_; print '$i = ', defined $i ? $i : '<undefined>'; print '$j = ', defined $j ? $j : '<undefined>'; print '$k = ', defined $k ? $k : '<undefined>'; } __DATA__ a b c d e f g h

    Output:

    $i = a $j = b $k = c $i = d $j = e $k = f $i = g $j = h $k = <undefined>

    -- Ken

Re: Save first n values from a file
by robby_dobby (Pilgrim) on Jan 13, 2014 at 05:57 UTC
    Others have offered varied solutions. Alternatively, you can use splice. Once you have read all the names into an array, you can loop through that array to gather items 3 at a time:
    while(@names) { my ($i, $j, $k) = splice (@names, 0, 3); printf('$i is %s, $j is %s, $k is %s', $i, $j, $k); print "\n"; }
    Note that if you have strict or warnings enabled, you will get errors like: "Use of uninitialized value $k in printf". You can add error/null checking here to handle all of these. This would also mutate the @names array - keep a defensive copy around. :-)
Re: Save first n values from a file
by Anonymous Monk on Jan 10, 2014 at 20:57 UTC
    Fastest way by far:
    • seek() to a position, relative to end-of-file, that you are quite sure is long enough to fit. ...
    • Read a string starting from that position.
    • Use a regex anchored at end-of-string to carve off the last three digits, e.g. /(\d+)\n(\d+)\n(\d+)$/ this assuming there are no whitespaces.
    • The numbers you want are $1, $2, $3. (If they aren't, then die() because your assumption about "what you are quite sure is long enough" wasn't.)
    You don't need to slog through an arbitrarily-long random access file just to find out what's at the end of it.
Re: Save first n values from a file
by pvaldes (Chaplain) on Jan 12, 2014 at 15:19 UTC
    use strict; use warnings; my @foo = (); while (<DATA>){ chomp; if ($. < 4){push @foo, $_}} print "my first variable is $foo[0]"; print "my second variable is $foo[1]"; print "my third variable is $foo[2]"; __DATA__ one two a beautiful tree, maybe an oak?

    no need to read after "n lines"

    And you can add also a fifth line to rename your variables and that's all:

     my ($ball,$dog,$bird) = ($fo[1],$fo[2],$fo[0]);
Re: Save first n values from a file
by Anonymous Monk on Jan 10, 2014 at 20:58 UTC
    Correction: "read a chunk of data regardless of 'string' boundaries." The actual bytes, please.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (8)
As of 2015-07-29 02:56 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 (260 votes), past polls