Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

perl – trying to sort an array of 'hashes' based on values

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

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 );
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading