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

Hello, I hope you can help me. I'm having a problem with sort dropping the last element of an array I need to print. The array is part of a hash, and I just need to sort the elements of the array and print them out. Unfortunately when I go to sort and print, the last element disappears. I know the last element is disappearing because I've gone and added code to tell me how many elements are in the array, and then to print them first by accessing each individual element, without sorting. What's weird is that when I sort the array, it comes back as the same size as the unsorted, but it doesn't print the last line. Here's the code, followed by an output of the script.
foreach $test (keys %Tests) { print "Test and students are\n $test:\n"; $" = "\n"; # Only do the sort and join with newlines # if there's more than one student. if (@{ $Tests{$test} } > 1){ @tempvar1 = sort( @{ $Tests{$test} }); $i = 0; #Making sure everything is sorted, and will #actually print. Had problems with lines being #dropped. $tempvar = @{ $Tests{$test} }; print $tempvar, "\n"; while ($i < @{ $Tests{$test} }){ print $Tests{$test}[$i]; print "\n"; $i++; } $tempvar2 = @tempvar1; print $tempvar2, "\n"; print "@tempvar1"; # print $tempvar1 . "hello\n"; # print join("|", sort @{ $Tests{$test} }); } else {print "@{ $Tests{$test} }\n";} print ",,,,,,,,,\n,,,,,,,,,\n"; }
Output:

Test and students are
Development:
4
"Drayton, xxx",,3 Years and 7 Months,,,,,,
"Areen, xxx",,3 Years and 9 Months,,,,,,
"Lyles, xxx",,4 Years and 0 Months,,,,,,
"Coleman, xxx",,3 Years and 9 Months,,,,,,
4
"Areen, xxx",,3 Years and 9 Months,,,,,,
"Coleman, xxx",,3 Years and 9 Months,,,,,,
"Drayton, xxx",,3 Years and 7 Months,,,,,,

Replies are listed 'Best First'.
Re: print dropping a line?
by tedrek (Pilgrim) on Jun 02, 2003 at 01:52 UTC

    I tried that under v5.8.0 Linux and it appeared to work fine. So the question is, what version of perl are you running? and what's your test data, the internal format.

    also use strict; use warnings; they are your friends

    You can also write that whole foreach loop much simpler something like this

    foreach my $test (keys %Tests) { print "Test is $test\n"; # This should print them all sorted print join("\n", sort @{$Tests{$test}}); # For checking the data, shouldn't be needed in production #print "Num before sort:", $#{$Tests{$test}} + 1, "\n"; #print join("\n", @{$Tests{$test}}); #@{$Tests{$test} = sort @{$Tests{$test}}; #print "Num after sort:", $#{$Tests{$test}} + 1, "\n"; #print join("\n", @{$Tests{$test}}); }

    Update: I used the same initial value for %Tests as edoc does below. (forgot to mention that)

      I'll second that. (Perl 5.8 on Linux)

      I used:

      my %Tests = ( Development => [ '"Drayton, xxx",,3 Years and 7 Months,,,,,,', '"Areen, xxx",,3 Years and 9 Months,,,,,,', '"Lyles, xxx",,4 Years and 0 Months,,,,,,', '"Coleman, xxx",,3 Years and 9 Months,,,,,,', ], ); and it printed: Test and students are Development: 4 "Drayton, xxx",,3 Years and 7 Months,,,,,, "Areen, xxx",,3 Years and 9 Months,,,,,, "Lyles, xxx",,4 Years and 0 Months,,,,,, "Coleman, xxx",,3 Years and 9 Months,,,,,, 4 "Areen, xxx",,3 Years and 9 Months,,,,,, "Coleman, xxx",,3 Years and 9 Months,,,,,, "Drayton, xxx",,3 Years and 7 Months,,,,,, "Lyles, xxx",,4 Years and 0 Months,,,,,,,,,,,,,,, ,,,,,,,,,

      cheers,

      J

Re: print dropping a line?
by Zaxo (Archbishop) on Jun 02, 2003 at 00:30 UTC

    You're getting snarled up in indexes. In perl it is better to print arrays as single arguments, forming a list argument for print. You can sort on the fly before printing. Since you want newlines between fields, we'll change the output field seperator to suit.

    { local $, = "\n"; print sort @{$Tests{$test}}; }

    Update You appear to have a foreach () {} else {} construct there. Is this really the code that's dropping a line? What you show shouldn't compile.

    After Compline,
    Zaxo

      the "hidden" '}' at the end of:

      else {print "@{ $Tests{$test} }\n";}

      means it's valid.. maybe not correct, but I don't think it's got to do with the problem..

      cheers,

      J

      Tried your code, and I still get the same thing.
      The last line still isn't printing.

      Thanks

Re: print dropping a line?
by halley (Prior) on Jun 02, 2003 at 14:41 UTC

    Two notes:

    First, please run perltidy on your script. The code should be as easy for the human eye to parse as it is for the interpreter to parse. People have been trying to read your code and getting tripped up on the brace matching.

    Second, though I haven't got a Linux box here to try it, I think your problem is a lack of a final newline. This can trip up some of Linux's terminal windows, for example.

    The desperate final line print ",,,,,,,,,\n,,,,,,,,,\n"; should print both groups of commas and a final newline, but maybe your output as demonstrated was from a test run without that line. When I ran your code verbatim (and the example %Tests above), the last output had no newline following the last item. Your terminal prompt probably just printed on top of your last and unterminated line of output.

    To diagnose this in the future, run your script and output it to a file: (foo >foo.txt). Then edit the file to see if it has the last line. If so, then it's your terminal's problem: it's obliterating the last bit of output to print your interactive shell prompt.

    The construct { $" = "\n"; print "@array"; } is equivalent to the construct: { print join("\n", @array); }. Neither one will follow the last item with your separator.

    Always print a newline last.

    --
    [ e d @ h a l l e y . c c ]

      Thanks everyone. I'm not at home right now, so I can't check out any of the stuff you suggested. And the reason the code is unreadable is becuase I spent an hour trying unsuccessfully to get various things to work. Again, thanks for your help.