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

Hi,

I just want to record a newbie impression here, that I'm finding things awkward when storing text as an array and trying to couple textlines with linenumbers ...

Am I doinng things too cumbersomely? I mean I do a "while (<>)" and put all the lines into an array - as any newbie would.

But in order not to lose the logical order of the text, I had to use a hash instead so I could (permanently) link each line with a linenumber.

The hash seem to have a crazy internal order for the lines, but I found out how to sort numerically on the key. The upshot is, I actually thought this would be a simple task, and my code is a little unwieldy already.

Should I really be using some DB module for this now? Especially as I want to start regexing the hash now, and making it behave like egrep (i'm on perl for win) and churning out a series of data as to where matches occur and so forth ....
  • Comment on line numbers and line content into hash

Replies are listed 'Best First'.
Re: line numbers and line content into hash
by tachyon (Chancellor) on Sep 22, 2004 at 23:14 UTC

    Hello. You don't need or want a hash. You want an ordinary array. Arrays have indexes, and you don't need while to get all the lines from a file into an array.....

    my @lines = <DATA>; chomp(@lines); my $line_num = 3; my $ary_index = $line_num -1; printf "Line number %d is '%s'\n", $line_num, $lines[$ary_index]; __DATA__ line 1 index 0 line 2 index 1 line 3 index 2 line 4 index 3 line 5 index 5

    Note that a Perl array starts with index 0, not one.

    cheers

    tachyon

Re: line numbers and line content into hash
by Zaxo (Archbishop) on Sep 22, 2004 at 23:20 UTC

    Are you doing something like this?

    my %hash $hash{$.} = $_ while <>;
    Nothing wrong with that.

    Why not use an array, though? my @lines = <>; The line number is implicit in the array index, and no sorting is needed.

    You can grep over the array as much as you wish and still get line numbers (minus 1), my @matched_idxs = grep {$lines[$_] =~ /$re/} 0 .. $#lines; and that array can be used in a slice or a pretty-printing loop.

    After Compline,
    Zaxo

Re: line numbers and line content into hash
by davido (Cardinal) on Sep 22, 2004 at 23:19 UTC

    If you're trying to preserve the order in which lines were read out of a file, and maintain a one-to-one relationship with lines to array elements, I don't see what the problem is. The following snippet is intentionally overly explicit. It could be done in a couple of lines (or less), but I wanted to make it clear what the mechanics are.

    my @array; while ( my $line = <DATA> ) { chomp; push @array, $line; } for( my $idx = 0; $idx <= $#array; $idx++ ) { my $line_no = $idx + 1; print "Line $line_no = $array[$idx]\n"; } __DATA__ Here's the first line Here's the second line Here is the third line Here is the forth line

    Just always keep in mind that arrays are zero-indexed.

    Hashes don't maintain order, and though it's possible to tie a hash to a class that keeps it sorted, most of the time you shouldn't be trying to enforce order on hashes. On the other hand, if you are using a hash for something where you need to see its keys in sorted order, just sort them.


    Dave

Re: line numbers and line content into hash
by waswas-fng (Curate) on Sep 22, 2004 at 23:15 UTC
    Huh?
    open INFILE, "<", '/var/tmp/infile' or die "ack! no infile: $!"; @slurp = <INFILE>; close INFILE; print "This is line 5:", $slurp[5-1], "\n"; # arrays start index at 0 so subtract # one from the line number to get the array index. print "This is line 12:", $slurp[12-1], "\n";


    -Waswas
Re: line numbers and line content into hash
by BrowserUk (Patriarch) on Sep 23, 2004 at 00:10 UTC

    Sounds like you should investigate Tie::File. It's ideal for this kind of thing.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: line numbers and line content into hash
by Gunth (Scribe) on Sep 22, 2004 at 23:17 UTC
    I might be missing what you're saying, but why create the hash to begin with? The array is ordered, and the index+1 will tell you the line number.
    -Will
thanks
by stabu (Scribe) on Sep 23, 2004 at 08:25 UTC
    I want to thank all you guys for the answers. I'm absorbing everything you've said. They've been really helpful in steering me clear of "hammer-to-crack-a-nut" city.
Re: line numbers and line content into hash
by sgc (Initiate) on Sep 23, 2004 at 12:33 UTC
    Hello Stabu , If you have pushed your lines into an array , then the index of your array implicitly couples the linenumber with the content of each element of the array. for ($i=0;$i<=$#ALL;$i++) { print "$i , $ALL$i" ; } cheers sgc