Your question has already been well-answered. I am posting code for 5 methods, for variety and comparison.
- Your original code, placed in a sort sub (++jettero)-- Simple!
- Schwartzian Transform -- Fast!
- Guttman-Rosler Transform -- Faster!
- Sort::Maker -- Concise!
- Sort::Key -- Even more concise!
The simple sort sub is probably best for your needs. Fast enough, concise enough, and requiring no extra modules.
The two transforms are included just as an illustration of how to write them yourself; they are more verbose than the simple sub, and
you would only need their speed if you had many teams, or if your method calls were slow.
Sort::Key and Sort::Maker are not core, but are almost as fast as the hand-coded transforms, and allow for very maintainable code.
Sort::Maker is my favorite.
use strict;
use warnings;
# Heavily abused fake object class
package Teams;
sub get_wins_total { $_[0]->{ WT } }
sub get_wins_division { $_[0]->{ WD } }
sub get_wins_home { $_[0]->{ WH } }
sub get_runs_scored { $_[0]->{ RS } }
sub get_runs_allowed { $_[0]->{ RA } }
sub get_reg_schedule_id { $_[0]->{ ID } }
sub print_me {
print map(sprintf("%7d\t", $_[0]->{$_}), qw( WT WD WH RS RA ID )),
+ "\n";
}
package main;
# Herkum's sort sub
sub standings {
$b->get_wins_total <=> $a->get_wins_total
or $b->get_wins_division <=> $a->get_wins_division
or $b->get_wins_home <=> $a->get_wins_home
or $b->get_runs_scored <=> $a->get_runs_scored
or $a->get_runs_allowed <=> $b->get_runs_allowed
or $a->get_reg_schedule_id <=> $b->get_reg_schedule_id
}
# Schwartzian Transform
sub sort_teams_by_standing_ST {
return
map { $_->[0] }
sort {
$b->[1] <=> $a->[1]
or $b->[2] <=> $a->[2]
or $b->[3] <=> $a->[3]
or $b->[4] <=> $a->[4]
or $a->[5] <=> $b->[5]
or $a->[6] <=> $b->[6]
}
map {[
$_,
$_->get_wins_total,
$_->get_wins_division,
$_->get_wins_home,
$_->get_runs_scored,
$_->get_runs_allowed,
$_->get_reg_schedule_id,
]} @_;
}
# Guttman-Rosler Transform
sub sort_teams_by_standing_GRT {
return @_[
map { unpack 'x[l6] l', $_ }
sort
map { pack 'l7',
-$_[$_]->get_wins_total,
-$_[$_]->get_wins_division,
-$_[$_]->get_wins_home,
-$_[$_]->get_runs_scored,
$_[$_]->get_runs_allowed,
$_[$_]->get_reg_schedule_id,
$_,
} 0..$#_
];
}
# CPAN module Sort::Maker
use Sort::Maker;
sub sort_teams_by_standing_SM;
make_sorter(
name => 'sort_teams_by_standing_SM',
qw( GRT ),
number => [ qw( descending unsigned ), code => sub { $_->get_wins_
+total } ],
number => [ qw( descending unsigned ), code => sub { $_->get_wins_
+division } ],
number => [ qw( descending unsigned ), code => sub { $_->get_wins_
+home } ],
number => [ qw( descending unsigned ), code => sub { $_->get_runs_
+scored } ],
number => [ qw( ascending unsigned ), code => sub { $_->get_runs_
+allowed } ],
number => [ qw( ascending unsigned ), code => sub { $_->get_reg_s
+chedule_id } ],
) or die "make_sorter: $@";
# CPAN module Sort::Key
use Sort::Key::Maker sort_teams_by_standing_SKM => sub {
$_->get_wins_total,
$_->get_wins_division,
$_->get_wins_home,
$_->get_runs_scored,
$_->get_runs_allowed,
$_->get_reg_schedule_id,
}, qw( -integer -integer -integer -integer integer integer );
my @teams = map { bless $_, 'Teams' } (
{ WT => 52, WD => 26, WH => 13, RS => 12, RA => 11, ID => 808 },
{ WT => 52, WD => 27, WH => 16, RS => 200, RA => 100, ID => 909 },
{ WT => 52, WD => 27, WH => 17, RS => 210, RA => 110, ID => 606 },
{ WT => 52, WD => 27, WH => 17, RS => 210, RA => 111, ID => 303 },
);
print "\n"; $_->print_me for sort standings @teams;
print "\n"; $_->print_me for sort_teams_by_standing_ST @teams;
print "\n"; $_->print_me for sort_teams_by_standing_GRT @teams;
print "\n"; $_->print_me for sort_teams_by_standing_SM @teams;
print "\n"; $_->print_me for sort_teams_by_standing_SKM @teams;
print "\n";
|