Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   Sorting hash of hashes (http://www.velocityreviews.com/forums/t915308-sorting-hash-of-hashes.html)

Justin C 11-21-2011 05:04 PM

Sorting hash of hashes
 

I have a hash of hashes containing sales orders. The hash is structured
(as below) order number -> line number -> item info. The dump of the
data below is edited for brevity, there are at least half a dozen other
fields at the bottom level of the hash.

I'm trying to sort the orders by order number and then line number so
that I can output them in the order they have been received - how our
customer would expect to see them.

My first sort appears to work OK, but the second level of sorting fails.
I'm missing something simple here, I'm sure, can someone remind me
please?

Justin.


Demo of how it doesn't work as I expect:

#!/usr/bin/perl

use strict;
use warnings;
use YAML;

my $tmp;
while (<DATA>) {
$tmp .= $_;
}
my $all_orders = Load($tmp);

for my $order (sort keys %$all_orders) {
print "Order: ", $order, "\n";
foreach my $line (sort { $all_orders->{$order}{$a} <=> $all_orders->{$order}{$b} } keys %{$all_orders->{$order}}) {
print "Line: ", $line, "\n";
}
}



__DATA__
---
1107/02454:
3859:
stock_code: WP/AAM/VIKINGS
3860:
stock_code: GB/AAM/VIKINGS
3872:
stock_code: WP/BTL/SEAOFSC
4356:
stock_code: GB/IM/FINALFS
1108/02859:
10:
stock_code: WP/KIS/KISSARM
17:
stock_code: AK/AC/LOGORUB
18:
stock_code: ST/AC/OVALLOG
73:
stock_code: WP/PF/BLOCKWA
76:
stock_code: WP/PF/DARKSIO
77:
stock_code: WP/PF/DIVISIE
90:
stock_code: SP/TEST/LOGO
1109/03591:
12:
stock_code: WP/IM/LIVEAFT
13:
stock_code: GB/IM/FEAROFT
14:
stock_code: SB/IM/LOGOFIN
20:
stock_code: SP/MOT/ACEOFSP
22:
stock_code: WP/KIS/CREATUR
24:
stock_code: WP/KIS/FACESPU
25:
stock_code: WP/KIS/KISSARM
38:
stock_code: WP/ACOO/EYESBLA
43:
stock_code: WP/HHOR/TASTETH
52:
stock_code: ST/KIS/CREATUR
57:
stock_code: ST/KIS/DESTROY
60:
stock_code: ST/KIS/DYNASTY
67:
stock_code: SP/KIS/LOGOFAC
69:
stock_code: ST/KIS/LOVEGUN
1109/03609:
415:
stock_code: BA/SFLY/OMEN
16:
stock_code: LA/IM/FINALFR
17:
stock_code: LA/QUE/LOGOAND
19:
stock_code: ST/MOT/BORNTOL
21:
stock_code: ST/MOT/HAMMERE
24:
stock_code: LA/KIS/LOGO
5:
stock_code: BA/FF/LOGOS
55:
stock_code: BA/FF/LOGOS
555:
stock_code: BA/FF/LOGOS




--
Justin C, by the sea.

Tony Mountifield 11-21-2011 06:16 PM

Re: Sorting hash of hashes
 
In article <5tcqp8-9cc.ln1@zem.masonsmusic.co.uk>,
Justin C <justin.1104@purestblue.com> wrote:
>
> I have a hash of hashes containing sales orders. The hash is structured
> (as below) order number -> line number -> item info. The dump of the
> data below is edited for brevity, there are at least half a dozen other
> fields at the bottom level of the hash.
>
> I'm trying to sort the orders by order number and then line number so
> that I can output them in the order they have been received - how our
> customer would expect to see them.
>
> My first sort appears to work OK, but the second level of sorting fails.
> I'm missing something simple here, I'm sure, can someone remind me
> please?


Yes, you are sorting on what the second level points at, (HASH(0x12345678)),
rather than the indices themselves. Try this line instead:

foreach my $line (sort { $a <=> $b } keys %{$all_orders->{$order}}) {

Another neat thing you can do is to have this near the top of the program:

sub numerically { $a <=> $b }

and then do this:

foreach my $line (sort numerically keys %{$all_orders->{$order}}) {

Cheers
Tony

> Justin.
>
>
> Demo of how it doesn't work as I expect:
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
> use YAML;
>
> my $tmp;
> while (<DATA>) {
> $tmp .= $_;
> }
> my $all_orders = Load($tmp);
>
> for my $order (sort keys %$all_orders) {
> print "Order: ", $order, "\n";
> foreach my $line (sort { $all_orders->{$order}{$a} <=> $all_orders->{$order}{$b} } keys
> %{$all_orders->{$order}}) {
> print "Line: ", $line, "\n";
> }
> }
>
>
>
> __DATA__
> ---
> 1107/02454:
> 3859:
> stock_code: WP/AAM/VIKINGS
> 3860:
> stock_code: GB/AAM/VIKINGS
> 3872:
> stock_code: WP/BTL/SEAOFSC
> 4356:
> stock_code: GB/IM/FINALFS
> 1108/02859:
> 10:
> stock_code: WP/KIS/KISSARM
> 17:
> stock_code: AK/AC/LOGORUB
> 18:
> stock_code: ST/AC/OVALLOG
> 73:
> stock_code: WP/PF/BLOCKWA
> 76:
> stock_code: WP/PF/DARKSIO
> 77:
> stock_code: WP/PF/DIVISIE
> 90:
> stock_code: SP/TEST/LOGO
> 1109/03591:
> 12:
> stock_code: WP/IM/LIVEAFT
> 13:
> stock_code: GB/IM/FEAROFT
> 14:
> stock_code: SB/IM/LOGOFIN
> 20:
> stock_code: SP/MOT/ACEOFSP
> 22:
> stock_code: WP/KIS/CREATUR
> 24:
> stock_code: WP/KIS/FACESPU
> 25:
> stock_code: WP/KIS/KISSARM
> 38:
> stock_code: WP/ACOO/EYESBLA
> 43:
> stock_code: WP/HHOR/TASTETH
> 52:
> stock_code: ST/KIS/CREATUR
> 57:
> stock_code: ST/KIS/DESTROY
> 60:
> stock_code: ST/KIS/DYNASTY
> 67:
> stock_code: SP/KIS/LOGOFAC
> 69:
> stock_code: ST/KIS/LOVEGUN
> 1109/03609:
> 415:
> stock_code: BA/SFLY/OMEN
> 16:
> stock_code: LA/IM/FINALFR
> 17:
> stock_code: LA/QUE/LOGOAND
> 19:
> stock_code: ST/MOT/BORNTOL
> 21:
> stock_code: ST/MOT/HAMMERE
> 24:
> stock_code: LA/KIS/LOGO
> 5:
> stock_code: BA/FF/LOGOS
> 55:
> stock_code: BA/FF/LOGOS
> 555:
> stock_code: BA/FF/LOGOS
>
>
>
>
> --
> Justin C, by the sea.



--
Tony Mountifield
Work: tony@softins.co.uk - http://www.softins.co.uk
Play: tony@mountifield.org - http://tony.mountifield.org

Jim Gibson 11-21-2011 06:43 PM

Re: Sorting hash of hashes
 
In article <5tcqp8-9cc.ln1@zem.masonsmusic.co.uk>, Justin C
<justin.1104@purestblue.com> wrote:

> I have a hash of hashes containing sales orders. The hash is structured
> (as below) order number -> line number -> item info. The dump of the
> data below is edited for brevity, there are at least half a dozen other
> fields at the bottom level of the hash.
>
> I'm trying to sort the orders by order number and then line number so
> that I can output them in the order they have been received - how our
> customer would expect to see them.
>
> My first sort appears to work OK, but the second level of sorting fails.
> I'm missing something simple here, I'm sure, can someone remind me
> please?


You are sorting on the /value/ of the second-level hash, not the /key/.
See below.

> Demo of how it doesn't work as I expect:
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
> use YAML;
>
> my $tmp;
> while (<DATA>) {
> $tmp .= $_;
> }
> my $all_orders = Load($tmp);
>
> for my $order (sort keys %$all_orders) {
> print "Order: ", $order, "\n";
> foreach my $line (sort { $all_orders->{$order}{$a} <=>
> $all_orders->{$order}{$b} } keys %{$all_orders->{$order}}) {


foreach my $line (
sort { $a <=> $b }
) keys %{$all_orders->{$order}} ) {

> print "Line: ", $line, "\n";
> }
> }
>
>
>
> __DATA__


[data snipped]

--
Jim Gibson

Justin C 11-22-2011 10:56 AM

Re: Sorting hash of hashes
 
On 2011-11-21, Tony Mountifield <tony@mountifield.org> wrote:
> In article <5tcqp8-9cc.ln1@zem.masonsmusic.co.uk>,
> Justin C <justin.1104@purestblue.com> wrote:
>>
>> I have a hash of hashes containing sales orders. The hash is structured
>> (as below) order number -> line number -> item info. The dump of the
>> data below is edited for brevity, there are at least half a dozen other
>> fields at the bottom level of the hash.
>>
>> I'm trying to sort the orders by order number and then line number so
>> that I can output them in the order they have been received - how our
>> customer would expect to see them.
>>
>> My first sort appears to work OK, but the second level of sorting fails.
>> I'm missing something simple here, I'm sure, can someone remind me
>> please?

>
> Yes, you are sorting on what the second level points at, (HASH(0x12345678)),
> rather than the indices themselves. Try this line instead:


Of course I am! D'oh! Sometimes you just can't see it for looking.

Thank you, and also thanks to Jim, for pointing out the error of my
ways.

>
> foreach my $line (sort { $a <=> $b } keys %{$all_orders->{$order}}) {
>
> Another neat thing you can do is to have this near the top of the program:
>
> sub numerically { $a <=> $b }
>
> and then do this:
>
> foreach my $line (sort numerically keys %{$all_orders->{$order}}) {


I quite like this, it's not anything less to type, but if there's a
whole bunch of sorting to be done it's very clear from the outset what
you're doing.

Justin.

--
Justin C, by the sea.


All times are GMT. The time now is 05:07 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57