Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Sort Hash array using date

by madtoperl (Hermit)
on Jan 15, 2009 at 16:24 UTC ( [id://736578] : perlquestion . print w/replies, xml ) Need Help??

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

Hi Monks,
I want to get the output of this hash array sorted by date.

Input for the hasharray

$dateOut = "2008-12-05"; $dSec = 0; $dMin=5; $dHour=9;
$dateOut = "2008-12-03"; $dSec = 2; $dMin=8; $dHour=5;
$dateOut = "2008-12-04"; $dSec = 0; $dMin=5; $dHour=8;

This is the part of code,
$dateOut = "$oDay".'-'."$oMon".'-'."$oYear"; #print"Date out => $dateOut\n"; $Date_Time{$dateOut}{$dSec}{$dMin}{$dHour} = 1 +; #Retrieving the hash array output foreach my $date ( sort keys %Date_Time ) { #print"Date=> $date\n"; foreach my $sec (sort keys %{$Date_Time{$date}}) { #print"Seconds=> $sec\n"; foreach my $minute (sort keys %{$Date_Time{$date}{$sec}}) +{ #print"Minute=> $minute\n"; foreach my $ hour (sort keys %{$Date_Time{$date}{$sec} +{$minute}}) { print"Date=>[$date] --> [$hour]:[$minute]:[$sec]\n +"; } } } } My Output: Date=>04-12-2008 --> 8:5:0 Date=>03-12-2008 --> 5:8:0 Date=>05-12-2008 --> 9:5:0 Expected output: Date=>03-12-2008 --> 5:8:0 Date=>04-12-2008 --> 8:5:0 Date=>05-12-2008 --> 9:5:0
Could any of you please help me to display the hash data sorted by date?

Thanks,
madtoperl

Replies are listed 'Best First'.
Re: Sort Hash array using date
by Corion (Patriarch) on Jan 15, 2009 at 16:46 UTC
Re: Sort Hash array using date
by linuxer (Curate) on Jan 15, 2009 at 16:56 UTC

    Why don't you store the values individually as keys, and format them directly when printing?

    I think of a structure ordered by "logical size" of each value:

    Year -> Month -> Day -> Hour -> Minute -> Second
    %Date_Time = ( Year => { Month => { Day => { Hour => { Minute => { Second => 1, }, }, }, }, }, ); for my $year ( sort keys %Date_Time ) { for my $month ( sort keys %{ $Date_Time{$year} } ) { for my $day ( sort keys %{ $Date_Time{$year}->{$month} } ) { my $time_r = $Date_Time{$year}->{$month}->{$day}; for my $hour ( sort keys %$time_r ) { for my $minute ( sort keys %{ $time_r->{$hour} } ) { for my $second ( sort keys %{ $time_r->{$hour}->{$minute} } +) { printf "Date: %d-%d-%d %02d:%02d:%02d\n", $day, $month, $year, $hour, $minute, $second; } } } } }
Re: Sort Hash array using date
by gone2015 (Deacon) on Jan 15, 2009 at 17:40 UTC

    You appear to want to sort into conventional time order, but your date string will sort by day number, then by month and then by year -- which is backwards... Then you are sorting by seconds, then minutes and then hours -- also backwards. Or is that really what you want ?

    The problem appears to be in two parts: (a) construct something that will sort into the order you want, (b) map that back to your actual keys. Perhaps:

    use strict ; use warnings ; my %Date_Time = ( '03-12-2008' => { '0' => { '8' => { '5' => 'a', '15' => 'b', }, '08' => { '22' => 'c', '05' => 'd', }, }, }, '04-12-2008' => { '0' => { '5' => { '8' => 'e', }, }, }, '05-12-2008' => { '0' => { '5' => { '9' => 'f', }, }, }, ) ; my @order ; foreach my $date (keys %Date_Time) { my ($d, $m, $y) = split(/-/, $date) ; my $o = sprintf("%04d%02d%02d", $y, $m, $d) ; foreach my $sec (keys %{$Date_Time{$date}}) { foreach my $min (keys %{$Date_Time{$date}{$sec}}) { foreach my $hour (keys %{$Date_Time{$date}{$sec}{$min}}) { + push @order, $o . sprintf("%02d%02d%02d", $hour, $min, $sec) . ":$date:$hour:$min:$sec" ; } ; } ; } ; } ; @order = sort @order ; foreach my $o (@order) { my (undef, $date, $hour, $min, $sec) = split(/:/, $o) ; print "Date=>$date $hour:$min:$sec = ", $Date_Time{$date}{$sec}{$min +}{$hour}, "\n" ; } ;
Re: Sort Hash array using date
by jethro (Monsignor) on Jan 15, 2009 at 17:14 UTC

    Your program works exactly as expected, I didn't change anything except for the initalization to test your code:

    #!/usr/bin/perl use warnings; use strict; my %Date_Time = ( "05-12-2008" =>{ 0 => { 5 => {9 => 1}}} , "03-12-2008" =>{ 2 => { 8 => {5 => 1}}} , "04-12-2008" =>{ 0 => { 5 => {8 => 1}}} ); #$dateOut = "$oDay".'-'."$oMon".'-'."$oYear"; #print"Date out => $dateOut\n"; #$Date_Time{$dateOut}{$dSec}{$dMin}{$dHour} = 1; #Retrieving the hash array output foreach my $date ( sort keys %Date_Time ) { #print"Date=> $date\n"; foreach my $sec (sort keys %{$Date_Time{$date}}) { #print"Seconds=> $sec\n"; foreach my $minute (sort keys %{$Date_Time{$date}{$sec}}) +{ #print"Minute=> $minute\n"; foreach my $ hour (sort keys %{$Date_Time{$date}{$sec} +{$minute}}) { print"Date=>[$date] --> [$hour]:[$minute]:[$sec]\n +"; } } } } output: Date=>[03-12-2008] --> [5]:[8]:[2] Date=>[04-12-2008] --> [8]:[5]:[0] Date=>[05-12-2008] --> [9]:[5]:[0]
Re: Sort Hash array using date
by setebos (Beadle) on Jan 15, 2009 at 16:57 UTC
    It's not a bad habit to check the FAQ-s 1st: perldoc -q whatever.
    They often give you a clue or the concrete example about the usage of the function you need.