App-rank
view release on metacpan or search on metacpan
script/rank view on Meta::CPAN
#!perl
our $DATE = '2018-05-01'; # DATE
our $VERSION = '0.007'; # VERSION
use 5.010001;
use strict;
use warnings;
use Getopt::Long qw(:config bundling no_ignore_case);
my %Opts = (
action => 'rank',
ignore_leading_blanks => 0,
calc_percentile => [],
reverse => 0,
sort => 'ascii',
field_separator => "\t",
sort_field => 0,
show_rank => 1,
show_percentile => 0,
rank => 'default',
# TODO: --dictionary-order, -d
# TODO: --ignore-nonprinting, -i
# TODO: --human-numeric-sort, -h
# TODO: --version-sort, -V
# TODO: --percentile-format=s
);
sub parse_cmdline {
my $res = GetOptions(
'action=s' => \$Opts{action},
'calc-percentile=s' => sub {
$Opts{action} = 'calc-percentile';
$Opts{calc_percentile} = [split /\s*,\s*/, $_[1]];
},
'ignore-leading-blanks|b' => \$Opts{ignore_leading_blanks},
'ignore-case|f' => \$Opts{ignore_case},
'reverse|r' => \$Opts{reverse},
'field-separator|t=s' => \$Opts{field_separator},
'numeric-sort|n' => sub { $Opts{sort} = 'numeric' },
'sort=s' => \$Opts{sort},
'sort-field=i' => \$Opts{sort_field},
'rank=s' => \$Opts{rank},
'show-rank!' => \$Opts{show_rank},
'show-percentile!' => \$Opts{show_percentile},
'-p' => sub { $Opts{show_percentile} = 1 },
'help|h' => sub {
print <<USAGE;
Usage:
rank [OPTIONS]... [INPUT]...
rank --help
For more details, see the manpage/documentation.
USAGE
exit 0;
},
'version|v' => sub {
no warnings 'once';
say "rank version ".($main::VERSION // 'dev');
exit 0;
},
);
exit 99 if !$res;
}
sub run {
my $fs = $Opts{field_separator};
my @data; # elem: [sortkey, $orig_line]
my $re_split_fields = qr/\Q$fs\E/;
while (defined (my $line = <>)) {
if ($Opts{ignore_leading_blanks}) {
$line =~ s/\A\s+//;
}
my @fields = split $re_split_fields, $line;
my $sortkey = $fields[$Opts{sort_field}] // '';
if ($Opts{ignore_case}) { $sortkey = lc $sortkey };
push @data, [$sortkey, $line];
}
my $sortsub;
if ($Opts{sort} eq 'numeric') {
if ($Opts{reverse}) {
$sortsub = sub { $_[0] <=> $_[1] };
} else {
$sortsub = sub { $_[1] <=> $_[0] };
}
} else {
if ($Opts{reverse}) {
$sortsub = sub { $_[1] cmp $_[0] };
} else {
$sortsub = sub { $_[0] cmp $_[1] };
}
}
@data = sort { $sortsub->($a->[0], $b->[0]) } @data;
# exact percentiles to calculate
my @percentiles;
for (@{ $Opts{calc_percentile} }) {
my $p = $_+0;
die "rank: Invalid percentile '$_', must be (0,100]\n"
unless $p > 0 && $p <= 100;
push @percentiles, $p;
}
@percentiles = sort {$b <=> $a} @percentiles;
# if we're using the 'no-skip' ranking system, we'll need to calculate
# the lowest ranking (highest number)first
my $lowest_rank;
( run in 1.010 second using v1.01-cache-2.11-cpan-5735350b133 )