use v5.14; use strict; use warnings; use List::MoreUtils qw( part ); use Sort::Key qw( keysort ); use Benchmark ':all'; package Person { use Moo; has name => (is => 'ro'); has title => (is => 'ro'); } my @employees = map { Person::->new( name => int(rand(999999)), title => int(rand(2))?'Staff':'Manager', ) } 0..200; sub obvious { my @sorted = sort { if ($a->title =~ /Manager/ and not $b->title =~ /Manager/) { -1; } elsif ($b->title =~ /Manager/ and not $a->title =~ /Manager/) { 1; } else { $a->name cmp $b->name; } } @employees; } sub subtle { my @sorted = sort { ($a->title !~ /Manager/) - ($b->title !~ /Manager/) or $a->name cmp $b->name; } @employees; } sub functional { my @sorted = map { sort { $a->name cmp $b->name } @$_ } part { $_->title !~ /Manager/ } @employees; } sub sortkey { my @sorted = map { keysort { $_->name } @$_ } part { $_->title !~ /Manager/ } @employees; } sub pure_schwarz { my @sorted = map $_->[1], sort { $a->[0] cmp $b->[0] } map [ $_->title =~ /Manager/ ? "A".$_->name : "B".$_->name, $_ ], @employees; } cmpthese(1000, { obvious => \&obvious, subtle => \&subtle, functional => \&functional, sortkey => \&sortkey, pure_schwarz => \&pure_schwarz, });