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


Dear Serene Monks,

My problem is this:

I would like to rearrange a list of data , to classify the list from the smallest hour to the latest hour

My list looks like :(* represents a data : number, ...)

* * * * * 02:50:00 * * *

* * * * * 01:30:00 * * *

* * * * * 05:40:00 * * *

Here is my code, but it does not seem to work.But I have no error messages.
my %Hash; while (<INFILE>) { my $Line = $_; my @Elements = split(";", $Line); my $hour = $Elements[5]; print STDOUT "L'heure vaut $hour\n"; if ($Elements[5] =~ /^(\d\d):(\d\d):(\d\d)/ ){ my $time = 3600*$1+60*$2+$3; $Hash{"$time"} = $Line; print STDOUT "the value of the Hash couple is $Hash{$time}"; } } close INFILE; print SDOUT "%Hash"; my @KEYS = keys(%Hash); sort(@KEYS); print STDOUT "The set of the keys is @KEYS"; my $hour_triee; foreach $hour_triee(@KEYS){ print OUTFILE "$Hash{$hour_triee}"; } close OUTFILE;

Replies are listed 'Best First'.
Re: modify the oder a list with the help of a hash table
by ikegami (Patriarch) on Jul 26, 2007 at 15:55 UTC

    sort returns the sorted list. It doesn't modify the argument.

    @KEYS = sort(@KEYS);

    Furthermore, since you're converting the timestamps to numbers, you want to do a numerical comparison instead of a lexical comparison.

    @KEYS = sort { $a <=> $b } @KEYS;

    But you could simply use $Elements[5] as the keys and a lexical comparison.

    Update: By the way, here's another way of doing what you want (fast):

    my @triee = map { substr($_, 8) } sort map { (split(/;/, $_))[5] . $_ } <INFILE>; foreach my $triee (@triee) { print OUTFILE $triee; }
Re: modify the oder a list with the help of a hash table
by FunkyMonk (Bishop) on Jul 26, 2007 at 16:55 UTC

    I'd like to add to other monks' comments by adding that

    use strict; use warnings;

    would have caught your mistake with sort.

Re: modify the oder a list with the help of a hash table
by snopal (Pilgrim) on Jul 26, 2007 at 16:00 UTC

    I try to remove all odor from my code, not just mask it.

    Wait! You must mean sorting order...

    @KEYS = sort @KEYS;

    Assignment of the result is missing from your code.

    Also, unless you have a logic issue (time not reported in 24 hour format) you should be able to string sort that time field directly.

    $Hash{$Element[5]} = $Line;
Re: modify the order a list with the help of a hash table
by shmf (Novice) on Jul 27, 2007 at 14:32 UTC
    Hi, try this! ;)
    I think it is more flexible that your code because it needs not your file lines' to have exactly one specific format.
    use warnings; use strict; use Cwd; my $path=cwd(); my %Hash; my $line; my $seconds=0; my $pathC = $path . '/data.txt'; open INFILE, "$pathC" or die "Cant open file $pathC\n"; while ($line = <INFILE>) { if($line =~ m/.*(\d{2}):(\d{2}):(\d{2}).*/){ $seconds = 3600*$1+60*$2+$3; $Hash{$seconds}=$line; } } close INFILE; for my $key (sort { $a <=> $b } (keys %Hash)){ print "$Hash{$key}"; }