我有一个perl脚本,需要经过几个文件并生成报告。
为了计算百分位数我正在做以下
my @values = 0;
while (my $line = <INPUTFILE>){
.....
push(@values, $line);
}
# Sort
@values = sort {$a <=> $b} @values;
# Print 95% percentile
print $values[sprintf("%.0f",(0.95*($#values)))];
这显然会在数组中预先保存所有值,然后计算百分位数,这可能对内存很重(假设有数百万个值),是否有更高效的内存方式?
答案 0 :(得分:3)
您可以处理文件两次:第一次运行只计算行数($.
)。从这个数字,你可以计算滑动窗口的大小,它只保留找到百分位数所需的最高数字(对于百分位数<50,你应该反转逻辑)。
#!/usr/bin/perl
use warnings;
use strict;
my $percentile = 95;
my $file = shift;
open my $IN, '<', $file or die $!;
1 while <$IN>; # Just count the number of lines.
my $line_count = $.;
seek $IN, 0, 0; # Rewind.
# Calculate the size of the sliding window.
my $remember_count = 1 + (100 - $percentile) * $line_count / 100;
# Initialize the window with the first lines.
my @window = sort { $a <=> $b }
map scalar <$IN>,
1 .. $remember_count;
chomp @window;
while (<$IN>) {
chomp;
next if $_ < $window[0];
shift @window;
my $i = 0;
$i++ while $i <= $#window and $window[$i] <= $_;
splice @window, $i, 0, $_;
}
print "$window[0]\n";