Sorting a multi-dimensional hash

I

ifiaz

Problem:

I populate a hash %Fnd with the following data
it loops through the file with 300000 lines of data.

###CODE

while (<>) {

if ( something == somethingelse) {

$Fnd{$Lic}{Count}++;

$cF = $Fnd{$Lic}{Count};

$Fnd{$Lic}{$cF}{ScanTimeDt} = substr($mScanTimeDt, 6, 2);
$Fnd{$Lic}{$cF}{ScanTime} = $ScanTime; #090000 (Sample Data)
$Fnd{$Lic}{$cF}{mFullScanTime} = $mFullScanTime; #20030317090000 (Sample data)
$Fnd{$Lic}{$cF}{IUMethod} = $IUMethod;
$Fnd{$Lic}{$cF}{IU} = $IU;
$Fnd{$Lic}{$cF}{Carrier} = $Carrier;
$Fnd{$Lic}{$cF}{CarCode} = $CarCode;
$Fnd{$Lic}{$cF}{FlightNo} = $FlightNo;
$Fnd{$Lic}{$cF}{Chute} = $Chute;
$Fnd{$Lic}{$cF}{TiltTimeDt} = substr($mTiltTimeDt, 6, 2);
$Fnd{$Lic}{$cF}{mTiltTimeDy} = $mTiltTimeDy;
$Fnd{$Lic}{$cF}{mTiltTime} = $mTiltTime;
$Fnd{$Lic}{$cF}{TStamp} = $TStamp;

}

}

###Looping through files end here.

## After the %Fnd is populated, I do a display of
## it in the appropriate format.

foreach $tmpLic (sort keys %Fnd) {

# do a display of the %Fnd hash one by one

}

__END__

Initially above loop was used to display, but later I
realize that I need to sort the hash not by the $Lic
in $Fnd{$Lic} but by the $Fnd{$Lic}{$Cf}{mFullScanTime}.

How can I have the hash sorted by my requirement?

I have tried various ways from newsgroups examples, etc.
but eventually fail. Could someone please help with
layman terms?

I am able to sort the hash when it is just one or two
dimensions but not more. I get utterly confused when
the gets more than two dimension.

I am newbie to perl actually to programming itself.


Thanks.
 
A

Anno Siegel

ifiaz said:
Problem:

I populate a hash %Fnd with the following data
it loops through the file with 300000 lines of data.

###CODE

No. What follows is pseudo-code. You improve your chances of getting
useful replies when you post runnable code.
while (<>) {

if ( something == somethingelse) {

$Fnd{$Lic}{Count}++;

$cF = $Fnd{$Lic}{Count};

$Fnd{$Lic}{$cF}{ScanTimeDt} = substr($mScanTimeDt, 6, 2);
$Fnd{$Lic}{$cF}{ScanTime} = $ScanTime; #090000 (Sample Data)
$Fnd{$Lic}{$cF}{mFullScanTime} = $mFullScanTime; #20030317090000 (Sample data) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$Fnd{$Lic}{$cF}{IUMethod} = $IUMethod;
$Fnd{$Lic}{$cF}{IU} = $IU;
$Fnd{$Lic}{$cF}{Carrier} = $Carrier;
$Fnd{$Lic}{$cF}{CarCode} = $CarCode;
$Fnd{$Lic}{$cF}{FlightNo} = $FlightNo;
$Fnd{$Lic}{$cF}{Chute} = $Chute;
$Fnd{$Lic}{$cF}{TiltTimeDt} = substr($mTiltTimeDt, 6, 2);
$Fnd{$Lic}{$cF}{mTiltTimeDy} = $mTiltTimeDy;
$Fnd{$Lic}{$cF}{mTiltTime} = $mTiltTime;
$Fnd{$Lic}{$cF}{TStamp} = $TStamp;

Why let everyone wade through all these lines? The only one relevant
to the problem is the one I highlighted.

Please learn how to indent properly. Again, the more readable your code
is, the better are your chances that someone will actually read it.
###Looping through files end here.

## After the %Fnd is populated, I do a display of
## it in the appropriate format.

foreach $tmpLic (sort keys %Fnd) {

# do a display of the %Fnd hash one by one

}

__END__

Initially above loop was used to display, but later I
realize that I need to sort the hash not by the $Lic
in $Fnd{$Lic} but by the $Fnd{$Lic}{$Cf}{mFullScanTime}.

You mean, sorting the hash *keys*.
How can I have the hash sorted by my requirement?

By supplying the corresponding comparison routinei (untested):

sort { $Fnd{$a}{$Cf}{mFullScanTime} <=> $Fnd{$b}{$Cf}{mFullScanTime} }
keys %Fnd;

Anno
 
I

ifiaz

No. What follows is pseudo-code. You improve your chances of getting
useful replies when you post runnable code.

Why let everyone wade through all these lines? The only one relevant
to the problem is the one I highlighted.
Please learn how to indent properly. Again, the more readable your code
is, the better are your chances that someone will actually read it.

Thanks for pointing out. I will follow accordingly.
You mean, sorting the hash *keys*.

I think by value. i.e. $Fnd{$Lic}{$cF}{mFullScanTime} = "20030317090000"
so I need to sort by the scan times on the right hand side of equal sign.
By supplying the corresponding comparison routinei (untested):

sort { $Fnd{$a}{$Cf}{mFullScanTime} <=> $Fnd{$b}{$Cf}{mFullScanTime} }
keys %Fnd;

One typical example is

$Fnd{"00123"}{"1"}{mFullScanTime} = ...
$Fnd{"00123"}{"2"}{mFullScanTime} = ...
$Fnd{"00123"}{"3"}{mFullScanTime} = ...
$Fnd{"00123"}{"4"}{mFullScanTime} = ...
$Fnd{"12345"}{"1"}{mFullScanTime} = ...
$Fnd{"12346"}{"1"}{mFullScanTime} = ...

Since, $cF is a variable that changes everytime, I don't know how
to pass the $cF inside the sort routine. So, I need to know how
I can pass the $cF inside the sort routine, so that the sort routine
can refer to each and every mFullScanTime of $Lic and $cF put
together and return the sorted result.

I am completely new to this. If my question is not phrased correctly
above, I apologise.
 
A

Anno Siegel

ifiaz said:
Thanks for pointing out. I will follow accordingly.


I think by value. i.e. $Fnd{$Lic}{$cF}{mFullScanTime} = "20030317090000"
so I need to sort by the scan times on the right hand side of equal sign.


One typical example is

$Fnd{"00123"}{"1"}{mFullScanTime} = ...
$Fnd{"00123"}{"2"}{mFullScanTime} = ...
$Fnd{"00123"}{"3"}{mFullScanTime} = ...
$Fnd{"00123"}{"4"}{mFullScanTime} = ...
$Fnd{"12345"}{"1"}{mFullScanTime} = ...
$Fnd{"12346"}{"1"}{mFullScanTime} = ...

Since, $cF is a variable that changes everytime, I don't know how
to pass the $cF inside the sort routine. So, I need to know how
I can pass the $cF inside the sort routine, so that the sort routine
can refer to each and every mFullScanTime of $Lic and $cF put
together and return the sorted result.

The operative term here is "put together". Apparently, every hash
entry can have multiple mFullScanTime's. The question is, how are
you going to use these for sorting? Pick one? If so, which one?
Use the average? Something else?

Without an answer to this there isn't much I can suggest.

Anno
 
I

ifiaz

sort { $Fnd{$a}{$Cf}{mFullScanTime} said:
The operative term here is "put together". Apparently, every hash
entry can have multiple mFullScanTime's. The question is, how are
you going to use these for sorting? Pick one? If so, which one?
Use the average? Something else?

Without an answer to this there isn't much I can suggest.

With help from your previous posting and a bit of trial and error
(actually several trials and errors), I managed to do the sorting.

Here it goes:

foreach $tmpLic (sort keys %Fnd) {
...
foreach $tmpCount (sort byScanTime keys %{$Fnd{$tmpLic}}) {
...
...
write;
}
}

##sort routine
sub byScanTime() {
$Fnd{$tmpLic}{$a}{mFullScanTime} <=>
$Fnd{$tmpLic}{$b}{mFullScanTime}
}

__END__

Although, I don't understand completely how it works, but I guess
I will manage to do the same with trial and error, next time I face it in a
different scenario.

Thank you.
 
T

Tad McClellan

ifiaz said:
##sort routine
sub byScanTime() {

Although, I don't understand completely how it works,


You can put some print() statements in the body of byScanTime()
and see what goes by...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top