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

The first sorted array crashes out because the data isnt split, but does return the first 0-9 elements of the array ( top 10 )...
the second sort works perfectly, but now i cant extract the first elements without an error, Please would you be so kind as to tell me where i am going wrong...
#### Old sort (that doesnt work properly ) with first 10 records extra +cted foreach my $k (keys %IND) { @indsort=(sort { $a <=> $b } @{$tmp}); foreach $line(@indsort[0..9]){ print "$line\n"; } }
So to my delight i fixed the sort on the array, but now the extraction of n elements isnt working, please see below:
#### New sort (which works!) with first 10 records NOT extracted foreach my $tmp (keys %IND) { my @lines; open(FILE, "+< tmp/$tmp.dat") or die "file:$tmp $!"; while (<FILE>) { chomp; my @line = split(','); push(@lines, \@line); } @lines = sort { $a->[0] <=> $b->[0]} @lines; foreach my $line (@lines) { print join(",", @{$line}) . "\n"; } }
gives the error:

Use of uninitialized value in array dereference...
in this line:
print join(",", @{$line}) . "\n";

Replies are listed 'Best First'.
Re: first elements in array, split join and sort problem
by samurai (Monk) on Sep 27, 2002 at 13:18 UTC
    It looks like one of your $lines is an uninitialized value. You could put in your foreach loop:

    next unless $line;

    But that's just ignoring the problem, not fixing it. But since we can't see sample data, it's hard to analyze WHY its uninitialized.

    --
    perl: code of the samurai

      a section of data... thank you..
      -25,AAR ,1303.000,00,1328.000 0,ABO ,5.575,00,5.575 36,ABS ,1243.000,00,1207.000 0,ABY ,122.500,00,122.500 -0.1,ACBD ,3.050,00,3.150 -1.5,ACG ,70.000,00,71.500 -20,ACI ,2459.000,00,2479.000 0,ACID ,4.250,00,4.250 -8,ACO ,1869.000,00,1877.000
Re: first elements in array, split join and sort problem
by BrowserUk (Patriarch) on Sep 27, 2002 at 18:19 UTC

    Couldn't see anything obviously wrong with your wrong with your code, so it's possible that your data contains blank lines as surmised by others.

    However, if your data contains blank lines they will get sorted to the top (Ie. first out) of your array, and by discarding them on output you will end up with less than the 10 lines you want. Better I think to discard them on input, which is what the grep in the code below does.

    I also thought that building an Array of Arrays in order to sort them was doing things the hard way, so I came up with the sort below. I don't know if it is a variation on one of the named sorts, or simply something I made up, but it works and will (I think, I haven't benchmarked it) be somewhat more efficient than your original.

    Another thing I've done is to NOT chomp the lines on input, as you are only going to have to put the newlines back on output.

    #! perl -sw use strict; my ($a1,$b1); #open(DATA, "+< tmp/$tmp.dat") or die "file:$tmp $!"; my @lines = sort { do{ ($a1) = $a =~ m/^([^,]+?),/; $a1; } <=> do{ ($b1) = $b =~ m/^([^,]+?),/; $b1; } } grep{ !m/^\s*$/ } <DATA>; print @lines[0 .. (scalar @lines >= 10) ? 9 : $#lines]; __DATA__ -25,AAR ,1303.000,00,1328.000 0,ABO ,5.575,00,5.575 36,ABS ,1243.000,00,1207.000 0,ABY ,122.500,00,122.500 -0.1,ACBD ,3.050,00,3.150 -1.5,ACG ,70.000,00,71.500 -20,ACI ,2459.000,00,2479.000 0,ACID ,4.250,00,4.250 -8,ACO ,1869.000,00,1877.000

    Gives

    # Output C:\test>201177 -25,AAR ,1303.000,00,1328.000 -20,ACI ,2459.000,00,2479.000 -8,ACO ,1869.000,00,1877.000 -1.5,ACG ,70.000,00,71.500 -0.1,ACBD ,3.050,00,3.150 0,ABY ,122.500,00,122.500 0,ACID ,4.250,00,4.250 0,ABO ,5.575,00,5.575 36,ABS ,1243.000,00,1207.000 C:\test>

    If you knew for sure that each file you are sorting would always have at least the number of lines you want to print, then you could do away with the need for any arrays at all and reduce the code to:

    #! perl -sw use strict; #open(DATA, "+< tmp/$tmp.dat") or die "file:$tmp $!"; my ($a1,$b1); print + (sort { do{ ($a1) = $a =~ m/^([^,]+?),/; $a1; } <=> do{ ($b1) = $b =~ m/^([^,]+?),/; $b1; } } grep{ !m/^\s*$/ } <DATA>)[0 .. 8];

    But that's beginning to look like a golf solution, so probably not worth the effort. However, it did lead me to noticing that in your top snippet you are printing  @lines[0 .. 9], ie. 10 lines but in your second post, the sample data you provided only had 9 lines which would of course be @lines[0 .. 8].

    Could this be why you were getting the original problem?


    (Would anyone care to venture an opinion as to whether this is a GRT or ST or someother named sort? If not, I'll take the liberty of calling it BUK's fizz:)

    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!

Re: first elements in array, split join and sort problem
by fglock (Vicar) on Sep 27, 2002 at 13:47 UTC

    This might help (will ignore empty lines if they exist):

    push(@lines, \@line) if @line;