Sorting hash of hashes

Discussion in 'Perl Misc' started by Justin C, Nov 21, 2011.

  1. Justin C

    Justin C Guest

    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.
     
    Justin C, Nov 21, 2011
    #1
    1. Advertising

  2. In article <>,
    Justin C <> 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: - http://www.softins.co.uk
    Play: - http://tony.mountifield.org
     
    Tony Mountifield, Nov 21, 2011
    #2
    1. Advertising

  3. Justin C

    Jim Gibson Guest

    In article <>, Justin C
    <> 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
     
    Jim Gibson, Nov 21, 2011
    #3
  4. Justin C

    Justin C Guest

    On 2011-11-21, Tony Mountifield <> wrote:
    > In article <>,
    > Justin C <> 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.
     
    Justin C, Nov 22, 2011
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Scott  Gilpin
    Replies:
    2
    Views:
    232
  2. Perl Learner

    Hashes of hashes or just one hash ?

    Perl Learner, Jun 8, 2005, in forum: Perl Misc
    Replies:
    11
    Views:
    226
  3. Tim O'Donovan

    Hash of hashes, of hashes, of arrays of hashes

    Tim O'Donovan, Oct 27, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    230
  4. IanW
    Replies:
    3
    Views:
    136
    Ian Stuart
    Dec 14, 2005
  5. Replies:
    3
    Views:
    227
Loading...

Share This Page