Home > Mobile >  perl - trying to sort an array of 'hashes' based on values
perl - trying to sort an array of 'hashes' based on values

Time:10-20

I'm populating an array with file detail values like this:

push(@local_files,{fname=>$bname, fdate=>$lfdate, fsize=>$lfsize});

then trying to sort these based on 'fname' descending order as shown in these examples and many others:

my @sorted=sort { $b->{'fname'} <=> $a->{'fname'} } \@local_files;

my @sorted=sort { $local_files['fname']{$b} cmp $local_files['fname']{$a} } @local_files;

Nothing I've tried has worked to sort this array, this is what I need help with.

But using dumper I can see that values are stored in the array

foreach my $whatever(@sorted){
        ## this works to dump contents of whatever
        print Dumper(\$whatever);

}

gives me output like this (snippet):

 {
              'fdate' => '88.837662037037',
              'fname' => 'Testfile997.txt',
              'fsize' => 4415
            },
            {
              'fdate' => '88.837662037037',
              'fname' => 'Testfile998.txt',
              'fsize' => 4415
            },

Eventually I want to be able to sort by any of the 3 values stored, but multiple searches have not been useful. Any help is appreciated - Thanks

CodePudding user response:

You almost had it the first time. Correct:

my @sorted = sort { $b->{ fname } cmp $a->{ fname } } @local_files;

You had a stray \, and you were performing a numerical comparison instead of a string comparison. (I removed the unneeded ', but that doesn't matter.)

It can also be done quite nicely with Sort-Key.

use Sort::Key qw( rskeysort );

my @sorted = rskeysort { $_->{ fname } } @local_files;

Note that you will have problems with both of the above if you have Testfile99 (rather than Testfile099) and Testfile100 (since 9 comes after 1). Using a natural sort will do the trick.

use Sort::Key::Natural qw( rnatkeysort );

my @sorted = rnatkeysort { $_->{ fname } } @local_files;

I want to be able to sort by any of the 3 values stored

use Sort::Key::Natural qw( rnatkeysort );

my %sorters = (
   by_fname_desc => sub { rnatkeysort { $_->{ fname } } @_ },
   ...
);

my $order = "by_fname_desc";  # Or whatever

my $sorter = $sorters{ $order }
   or die( "Unknown order `$order`" );

my @sorted = $sorter->( @local_files );
  • Related