![]() |
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. |
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 |
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 |
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.