Velocity Reviews > Perl > Sorting a multi-dimensional hash

# Sorting a multi-dimensional hash

ifiaz
Guest
Posts: n/a

 11-11-2003
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.
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.

Anno Siegel
Guest
Posts: n/a

 11-11-2003
ifiaz <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> 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.

> }
>
> }

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

ifiaz
Guest
Posts: n/a

 11-12-2003
> No. What follows is pseudo-code. You improve your chances of getting
> useful replies when you post runnable code.
>
> > \$Fnd{\$Lic}{\$cF}{mFullScanTime} = \$mFullScanTime; #20030317090000 (Sample data)

> Why let everyone wade through all these lines? The only one relevant
> to the problem is the one I highlighted.
> 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.

> > 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;
>

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.

Anno Siegel
Guest
Posts: n/a

 11-12-2003
ifiaz <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> > No. What follows is pseudo-code. You improve your chances of getting
> > useful replies when you post runnable code.
> >
> > > \$Fnd{\$Lic}{\$cF}{mFullScanTime} = \$mFullScanTime; #20030317090000

> (Sample data)
> > Why let everyone wade through all these lines? The only one relevant
> > to the problem is the one I highlighted.
> > 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.
>
> > > 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;
> >

>
> 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

ifiaz
Guest
Posts: n/a

 11-13-2003
> > > sort { \$Fnd{\$a}{\$Cf}{mFullScanTime} <=> \$Fnd{\$b}{\$Cf}{mFullScanTime} }
> > > keys %Fnd;
> > >

> >

>
> 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.

Guest
Posts: n/a

 11-13-2003
ifiaz <(E-Mail Removed)> wrote:

> ##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...

--
http://www.velocityreviews.com/forums/(E-Mail Removed) Perl programming
Fort Worth, Texas