Perl命中计数器用于多个范围,其他语言中的选项?

Perl命中计数器用于多个范围,其他语言中的选项?,perl,Perl,回来征求你的意见。我已经编写了一个perl脚本,它将特定数字的点击数计算到用户定义的容器中。例如,这是我的数据文件: 12 14 15 20 21 我想知道我在以下范围内的点击率: 1-19 20-29 30-39 所以结果会是这样的 1-19 3 20-29 2 30-39 0 我首先将数据保存到一个散列(datahash),然后将我的范围保存到另一个散列(rangehash),然后基本上检查datahash中的所有数据点,并检查值是否在rangehash的范围内 问题是,

回来征求你的意见。我已经编写了一个perl脚本,它将特定数字的点击数计算到用户定义的容器中。例如,这是我的数据文件:

12
14
15
20
21
我想知道我在以下范围内的点击率:

1-19
20-29
30-39
所以结果会是这样的

1-19    3
20-29   2
30-39   0
我首先将数据保存到一个散列(datahash),然后将我的范围保存到另一个散列(rangehash),然后基本上检查datahash中的所有数据点,并检查值是否在rangehash的范围内

问题是,对于datahash中的每个数据点,我循环遍历所有rangehash值,并在找到数据点所在的范围后退出。这对于一些数据点来说是好的,但是现在我有至少200万个数据点和50000个范围的文件,所以循环所有这些只需要永远

我想知道是否有人会有更好的解决方案,而不仅仅是在整个过程中循环。对其他语言的建议很受欢迎

最好的


Sakti最简单的方法可能是将数字与散列相加,然后将相应范围的散列切片相加。您还可以使用数组而不是散列,因为您可以使用数字作为索引。这可能会创建非常大的空哈希,这是浪费,但它简化了密钥生成,因为坏索引会发出警告

use strict;
use warnings;
use List::Util 'sum';

my %nums;
while (<DATA>) {
    s/\D+//g;     # remove junk
    $nums{$_}++;  # count number
}
my $low = 1;
for my $high (qw(19 29 39)) {
    my $sum =  sum(0,                      # to avoid undef return value
                   grep defined,           # avoid uninitialized warnings
                   @nums{$low .. $high});  # hash slice for our range
    print "$low - $high : $sum\n";
    $low = $high + 1;                      # set new low range
}

__DATA__
12
14
15
20
21

以下速度将非常快,尽管它假定不会出现零:

my @buckets = (0) x 4;
++$buckets[ $_ / 10 ] while <>:
print " 1-19: ".( $buckets[0] + $buckets[1] )."\n";
print "20-29: $buckets[2]\n";
print "30-39: $buckets[3]\n";
my@bucket=(0)x 4;
++$bucket[$\u10]同时:
打印“1-19:”。($bucket[0]+$bucket[1])。“\n”;
打印“20-29:$bucket[2]\n”;
打印“30-39:$bucket[3]\n”;
以下更通用的解决方案实际上可能更快:

use List::Util qw( sum );
++$counts[$_] while <>:
print " 1-19: ".( sum 0, @counts[ 1..19] )."\n";
print "20-29: ".( sum 0, @counts[20..29] )."\n";
print "30-39: ".( sum 0, @counts[30..39] )."\n";
use List::Util qw(sum);
++$counts[$\ux]同时:
打印“1-19:”(总和0,@counts[1..19])。“\n”;
打印“20-29:”(总和0,@counts[20..29])。“\n”;
打印“30-39:”(总和0,@counts[30..39])。“\n”;
这仅适用于用户定义的BIN,即无法轻松计算为
int($x/100)*100
或类似值的BIN

最近在这里或perlmonks上也有一个类似的问题(我很难找到),IMO的最佳答案是“排序垃圾箱的上限,然后使用二进制搜索”

对于50K箱,如果每个数据点有16个
if
s,这可能是正常的(当然不是“永远”)


根据数据的不同,可以应用一些缓存来进一步提高速度。例如,可以将数据四舍五入到预期间隔的1/1000(最后一个料位-第一个料位),只检查覆盖该部分的料位。(这是我编造的,但可能有用,也可能无效。)

谢谢TLP!我们将对此进行测试,并检查它如何减少计算时间,谢谢!交叉张贴在。初始化阵列是多余的<代码>++将自动将undef转换为0。另外,
map 0,0..3
aka
(0)x 4
。您可能也不打算使用
%
,但@TLP使用
/
,这并不是多余的,因为它可以防止打印undef的尝试。
use List::Util qw( sum );
++$counts[$_] while <>:
print " 1-19: ".( sum 0, @counts[ 1..19] )."\n";
print "20-29: ".( sum 0, @counts[20..29] )."\n";
print "30-39: ".( sum 0, @counts[30..39] )."\n";