5

我有一个 perl 脚本,它通过几个 gig 的文件并生成一个报告。

为了计算百分位数,我正在执行以下操作

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)))];

这显然将所有值预先保存在一个数组中,然后计算百分位数,这可能会占用大量内存(假设有数百万个值),是否有更高效的内存方式来执行此操作?

4

1 回答 1

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";
于 2013-08-13T12:37:01.337 回答