Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically sorting array of hash by multiple keys in perl

Tags:

perl

While looking for some pointers, on how to sort array of hash by multiple values, I came across the following solution: Sorting array of hash by multiple keys.

But, cannot seem to figure out a way to do this dynamically.

Say, if the number of parameters (here: hash key) that one would like to sort would depend on user input.

Using the same example, as used by the user in the linked question:

$arr_ref = [ { 'brand' => 'A',
           'supplier' => 'X',
           'PO' => '2'
          },
          { 'brand' => 'B',
            'supplier' => 'Y',
            'PO' => '1'       
          },
          { 'brand' => 'B',
            'supplier' => 'X',
            'PO' => '2'           
          },
          { 'brand' => 'A',
            'supplier' => 'X',
            'PO' => '1'
          },
          { 'brand' => 'B',
            'supplier' => 'X',
            'PO' => '1'           
          }

];

The user can provide whether they want to sort it by just 'brand' , 'brand' and 'supplier' or all three of them.

like image 478
iDev Avatar asked Nov 20 '25 03:11

iDev


1 Answers

Create a subroutine that does the sorting. It accepts any number of keys to do the comparison:

use strict;
use warnings;

my @array = (
    { 'brand' => 'A', 'supplier' => 'X', 'PO' => '2' },
    { 'brand' => 'B', 'supplier' => 'Y', 'PO' => '1' },
    { 'brand' => 'B', 'supplier' => 'X', 'PO' => '2' },
    { 'brand' => 'A', 'supplier' => 'X', 'PO' => '1' },
    { 'brand' => 'B', 'supplier' => 'X', 'PO' => '1' },
);

sub custom_sort {
    my ($x, $y, @keys) = @_;
    for (@keys) {
        my $cmp = $x->{$_} cmp $y->{$_};
        return $cmp if $cmp;
    }
    return 0;
}

my @sorted = sort {custom_sort($a, $b, 'brand', 'supplier', 'PO')} @array;

use Data::Dump;
dd @sorted;

Outputs:

(
  { brand => "A", PO => 1, supplier => "X" },
  { brand => "A", PO => 2, supplier => "X" },
  { brand => "B", PO => 1, supplier => "X" },
  { brand => "B", PO => 2, supplier => "X" },
  { brand => "B", PO => 1, supplier => "Y" },
)
like image 77
Miller Avatar answered Nov 22 '25 16:11

Miller



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!