I'm trying to sort the following data structure in Perl, by location_id.
my $employees = $dbh->selectall_arrayref(qq[
SELECT name, type, code, emp_cat_id,
percentage, location_id
FROM table_1
],{ Slice => {} });
for my $row (@$employees) {
push @{
$args->{employees}{ $row->{emp_cat_id} }
}, $row;
}
Example:
123 => [
{
percentage => 0.25,
code => "XYZ",
name => "John Doe",
type => "pt",
location_id => 001,
emp_cat_id => 123
}
],
555 => [
{
percentage => 0.50,
code => "ZZZ"
name => "Chris Cringle",
type => "ft",
location_id => 007,
emp_cat_id => 555
},
{
percentage => 0.25,
code => "XXX"
name => "Tom Thompson",
type => "pt",
location_id => 002,
emp_cat_id => 555
}
]
For every emp_cat_id, I need the structure to have the location_ids in asc order.
I've tried the following, but I get "useless use of sort in void context at line #" or "useless use of sort in scalar context at line #" errors.
$args->{employees} = sort {
$a->{location_id} <=> $b->{location_id}
} $args->{employees};
Any help understanding the sort is appreciated!
CodePudding user response:
So, you have a hashref where each element is an arrayref of hashrefs that should be sorted based on a key of that inside hashref?
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my $hashref = {
123 => [
{
percentage => 0.25,
code => "XYZ",
name => "John Doe",
type => "pt",
location_id => 001,
emp_cat_id => 123
}
],
555 => [
{
percentage => 0.50,
code => "ZZZ",
name => "Chris Cringle",
type => "ft",
location_id => 007,
emp_cat_id => 555
},
{
percentage => 0.25,
code => "XXX",
name => "Tom Thompson",
type => "pt",
location_id => 002,
emp_cat_id => 555
}
]
};
foreach my $arrayref (values %$hashref) {
@$arrayref = sort { $a->{location_id} <=> $b->{location_id} } @$arrayref;
}
print Dumper($hashref);
The important part you're missing is in dereferencing the arrayrefs. @$arrayref
instead of just $arrayref
.
CodePudding user response:
The problem is that you are sorting the array(ref) at emp_cat_id
of 555
, then of 123
, and so need to dereference for sorting those arrayrefs. So
foreach my $id (keys $args->{employees}) {
@{ $args->{employees}{$id} } = sort {
$a->{location_id} <=> $b->{location_id}
}
@{ $args->{employees}{$id} }
}
(tested with the structure shown in the question, omitted here)†
Doing anything like this loses 007
into 7
. This is of course possible to fix, let me know if it matters.
If you really have only the key employees
then consider extracting the $args->{employees}
hashref and working with that. It'll be way easier
use Storable qw(dclone);
my $employees = dclone $args->{employees}; # need deep copy
† Oh well, here's the whole thing
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd);
my $args = {
employees => {
123 => [
{
percentage => 0.25,
code => "XYZ",
name => "John Doe",
type => "pt",
location_id => 001,
emp_cat_id => 123
}
],
555 => [
{
percentage => 0.50,
code => "ZZZ",
name => "Chris Cringle",
type => "ft",
location_id => 007,
emp_cat_id => 555
},
{
percentage => 0.25,
code => "XXX",
name => "Tom Thompson",
type => "pt",
location_id => 002,
emp_cat_id => 555
}
]
}
};
foreach my $id (keys $args->{employees}) {
@{ $args->{employees}{$id} } = sort {
$a->{location_id} <=> $b->{location_id}
}
@{ $args->{employees}{$id} }
}
dd $args;