burgerc has asked for the wisdom of the Perl Monks concerning the following question:

I have an array that stores a hash. I would like to sort the array on one of the fields in the hash. Here is how I create the array
my @statements = (); for (@{ $data->{'mail-item'} }) { my %entry; $entry{job} = $_->{'mail-jobnum'}; $entry{product} = $_->{'mail-prodnum'}; $entry{statement_date} = $_->{'mail-statement-date'}; push(@statements, {%entry}); }
How would I sort the @statements array? I would like to sort it on the $entry{statement_date}.

The ultimate goal here is to display all statements in date orderd.

Thanks

Replies are listed 'Best First'.
Re: Sorting an Array
by toolic (Bishop) on Jul 31, 2014 at 13:48 UTC
Re: Sorting an Array
by McA (Priest) on Jul 31, 2014 at 13:52 UTC

    Hi,

    one part of this sorting job is the possibility to compare the values by which you want to sort. In this case the dates stored in entry{statement_date}. So you have to convert this date to a comparable value.

    What is the format of this date?

    McA

Re: Sorting an Array
by choroba (Cardinal) on Jul 31, 2014 at 17:12 UTC
    Note that creating an anonymous hash from lexical %entry is not needed. You can directly store a reference to it, as my will create a new one in the next iteration of the loop:
    push @statements, \%entry;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Sorting an Array
by burgerc (Novice) on Jul 31, 2014 at 18:27 UTC
    Thanks everyone. The sorting script worked. Not sure I understand the last comment about using my %entry. I'm sure this may help in speed of script. So I would love some further clarification on that. Also I made a slight change in sorting script to get a descending order. here is the final code.
    for (@{ $data->{'mail-item'} }) { my %entry; $entry{job} = $_->{'mail-jobnum'}; $entry{product} = $_->{'mail-prodnum'}; $entry{statement_date} = $_->{'mail-statement-date'}; push(@statements, {%entry}); } @statements = sort by_date @statements; $c->stash->{statements} = \@statements; sub by_date { my $dateA = $a->{statement_date}; my $dateB = $b->{statement_date}; $dateA =~ s!(\d\d)/(\d\d)/(\d\d\d\d)!$3$1$2!; $dateB =~ s!(\d\d)/(\d\d)/(\d\d\d\d)!$3$1$2!; $dateB cmp $dateA; }

      Not sure I understand the last comment about using my %entry. I'm sure this may help in speed of script. So I would love some further clarification on that.

      This refers to the for loop where you're pushing entries onto your @statement array. You're explicitely constructing a named hash, %entry, each time, but this isn't necessary; you can just as well do this:

      for (@{ $data->{'mail-item'} }) { push @statements, { job => $_->{'mail-jobnum'}, product => $_->{'mail-prodnum'}, statement_data => $_->{'mail-statement-date'} }; }

      Or, since you only have one statement in your loop body now, you can even use for as a statement modifier:

      push @statements, { job => $_->{'mail-jobnum'}, product => $_->{'mail-prodnum'}, statement_data => $_->{'mail-statement-date'} } for (@{ $data->{'mail-item'} });

      Although I personally consider this less readable than the "regular" loop above.

Re: Sorting an Array
by burgerc (Novice) on Jul 31, 2014 at 16:19 UTC
    the date format is 05/21/2014
      Haven't tried it out, but I think this would sort them.
      @statements = sort by_date @statements; sub by_date { my $dateA = $a->{statement_date}; my $dateB = $b->{statement_date}; $dateA =~ s!(\d\d)/(\d\d)/(\d\d\d\d)!$3$1$2!; $dateB =~ s!(\d\d)/(\d\d)/(\d\d\d\d)!$3$1$2!; $dateA cmp $dateB; }