Perl数组语法

时间:2011-11-13 23:42:19

标签: arrays perl counting

我的文件中包含1e8个数字,大小从1到999.我需要读取每个文件并保存每个文件中找到的每个数字的报告。我认为设置一个所有零的常量数组,然后使用我刚刚读取的数字作为索引递增会给我答案。执行此操作的Perl语法不是我所期望的。并非所有数字都必然出现。也许哈希是一种方法,但阵列可能只有几个洞。有帮助吗?感谢。

3 个答案:

答案 0 :(得分:3)

执行此操作的Perl语法不是我所期望的。

展示你的作品

并非所有数字都必然出现。

跳过零(如果是块,则为简单,请参阅http://perldoc.perl.org/perlintro.html

也许散列是一种可行的方法,但数组可能只有几个漏洞。

是的,散列很自然,请参阅perlfaq4,搜索"计算"," uniq"和"重复&#34 ;

答案 1 :(得分:3)

Tom Duff(Duff设备的创造者):“如果你的代码太慢,你必须加快速度。如果没有更好的算法,你必须修剪周期。

我不同意这是哈希最适合的情况。当然,散列是惯用的,它是perlfaq4中提到的方法,它不会浪费你的计数器容器中的元素。但他说的是1到999之间的100_000_000个整数。柜台容器中使用的元素数量是微不足道的。获得计数所需的迭代次数非常重要。 100,000,000次迭代需要花费大量时间。

如果我们使用数组,我们会抛弃索引为零的元素。如果所有整数都是相同的值,我们会扔掉998个元素。那是一件大事吗?另一方面,即使两者都索引到一个数组,并索引到一个哈希聚合到O(1)操作,Big-O表示法只能告诉部分故事。并且'n'是总整数(100,000,000),数组方法和哈希方法都是O(n)运算。因此,它归结为哪种方法在计算上更有效。即使数组查找和散列查找都是O(1),但事实证明散列查找需要更多的循环才能执行。

迭代超过100,000,000个整数并递增计数器需要时间。但事实证明,在哈希内部比在数组中花费更多时间。我知道这是从“常见习语”的角度来看是亵渎神灵的。但这可能是一个非常特殊的情况,其中计算效率比惯用代码更重要,并且比使用数组作为计数器的更大内存占用更重要。

以下是一些代码,展示了我所说的内容:

use strict;
use warnings;
use Benchmark  qw/ cmpthese /;
use List::Util qw/ max min  /;
use Test::More;
use Readonly;



Readonly my $datasize => 100_000_000;

Readonly my $test_size => 100_000;

my @array_results = keys count_in_array( $test_size );
my @hash_results  = keys count_in_hash(  $test_size );

is( max( @array_results ), 999, "max( keys count_in_array() ) in range." );
is( min( @array_results ),   1, "min( keys count_in_array() ) in range." );
is( max( @hash_results  ), 999, "max( keys  count_in_hash() ) in range." );
is( min( @hash_results  ),   1, "min( keys  count_in_hash() ) in range." );
done_testing();    



cmpthese( 5, {
    array => sub{ my $results = count_in_array() },
    hash  => sub{ my $results = count_in_hash()  },
} );




sub count_in_array {
    my @container;
    for( 1 .. $datasize ) {
        $container[ int( rand( 999 ) ) + 1 ]++;
    }
    return {
        map{ 
                $container[$_] > 0 
                    ? ( $_ => $container[$_] ) 
                    : () 
        } 1 .. $#container
    };
}



sub count_in_hash {
    my %container;
    for( 1 .. $datasize ) {
        $container{ int( rand ( 999 ) ) + 1 }++;
    }
    return \%container;
}

以下是该基准测试的结果:

ok 1 - max( keys count_in_array() ) in range.
ok 2 - min( keys count_in_array() ) in range.
ok 3 - max( keys  count_in_hash() ) in range.
ok 4 - min( keys  count_in_hash() ) in range.
1..4
      s/iter  hash array
hash    24.9    --  -42%
array   14.5   72%    --

这是阵列方法的一大胜利(它快72%)。如果这仍然太慢,可以使用Inline :: C来使用一组int重写数组方法来修剪周期。这仍然会快一个数量级。

这可能是保证优化的关键3%。

那么我们如何才能减轻脱离公认惯用语的影响呢?我们确保记录我们正在做的事情,以便将来的读者(包括我们自己在未来)了解正在做什么,以及为什么以一种我们不熟悉的方式完成它。

只是我的.02。

答案 2 :(得分:0)

根据系统排序实用程序的质量,在命令行:

sort giant-file.txt | uniq -c > giant_file_counts.txt