我的文件中包含1e8个数字,大小从1到999.我需要读取每个文件并保存每个文件中找到的每个数字的报告。我认为设置一个所有零的常量数组,然后使用我刚刚读取的数字作为索引递增会给我答案。执行此操作的Perl语法不是我所期望的。并非所有数字都必然出现。也许哈希是一种方法,但阵列可能只有几个洞。有帮助吗?感谢。
答案 0 :(得分:3)
执行此操作的Perl语法不是我所期望的。 的
展示你的作品
并非所有数字都必然出现。
跳过零(如果是块,则为简单,请参阅http://perldoc.perl.org/perlintro.html)
也许散列是一种可行的方法,但数组可能只有几个漏洞。 的
是的,散列很自然,请参阅perlfaq4
,搜索"计算"," uniq"和"重复&#34 ;
答案 1 :(得分:3)
我不同意这是哈希最适合的情况。当然,散列是惯用的,它是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