in reply to
Unusual sorting requirements; comparing three implementations.
You can exploit that fact that sort is stable, and do two passes over the data:
sub two_pass {
my @sorted =
sort { $b->title =~ /Manager/ <=> $a->title =~ /Manager/ }
sort { $a->name cmp $b->name }
@employees;
}
Moo wouldn't install on my machine, so I used Mo instead for benchmarking:
Rate obvious subtle two_pass functional
obvious 173/s -- -22% -30% -61%
subtle 222/s 28% -- -11% -50%
two_pass 249/s 44% 12% -- -44%
functional 444/s 156% 100% 79% --
Of course it does more than necessary (splitting into managers and non-managers first is less work, because the lists to sort are shorter), but the speed still isn't too bad.
Update: and here's a Perl 6 solution:
use v6;
class Person {
has $.name;
has $.title;
}
sub person($name, $title) { Person.new(:$name, :$title) };
my @employees =
person("Eve", "Tech Support"),
person("Alice", "Sales Manager"),
person("Dave", "Janitor"),
person("Fred", "Receptionist"),
person("Bob", "Customer Services"),
person("Greg", "Finance Manager"),
person("Carol", "Marketing Manager"),
;
my @sorted =
@employees.classify({ .title ~~ /Manager/ ?? 'manager' !! 'staff'}
+)\
.sort.map(*.value.sort(*.name));
say .perl for @sorted;
Output:
Person.new(name => "Alice", title => "Sales Manager")
Person.new(name => "Carol", title => "Marketing Manager")
Person.new(name => "Greg", title => "Finance Manager")
Person.new(name => "Bob", title => "Customer Services")
Person.new(name => "Dave", title => "Janitor")
Person.new(name => "Eve", title => "Tech Support")
Person.new(name => "Fred", title => "Receptionist")
.classify returns a Hash, and .sort on a Hash returns a list of Pair object, sorted by key and then by value. Since 'manager' lt 'staff', this puts all the managers first. Then each of the lists is sorted by name.