与问题类似 unix - count occurrences of character per line/field 但是对于线上每个位置的每个角色。
给出每1e7行约500个字符的文件, 我想要一个二维的汇总结构 $摘要{' A'' B'' C'' 0'' 1'&# 39; 2'} [pos 0..499] = count_integer 它显示了每个字符在该行的每个位置使用的次数。尺寸顺序都可以。
我的第一个方法在阅读时做了++ summary {char} [pos], 但由于很多线都是一样的, 首先计算相同的线条要快得多 然后一次总结摘要{char} [pos] + = n
是否有比以下类似C的2d循环更惯用或更快的方式?
#!perl
my ( %summary, %counthash ); # perl 5.8.9
sub method1 {
print "method1\n";
while (<DATA>) {
my @c = split( // , $_ );
++$summary{ $c[$_] }[$_] foreach ( 0 .. $#c );
} # wend
} ## end sub method1
sub method2 {
print "method2\n";
++$counthash{$_} while (<DATA>); # slurpsum the whole file
foreach my $str ( keys %counthash ) {
my $n = $counthash{$str};
my @c = split(//, $str);
$summary{ $c[$_] }[$_] += $n foreach ( 0 .. $#c );
} #rof my $str
} ## end sub method2
# MAINLINE
if (rand() > 0.5) { &method1 } else { &method2 }
print "char $_ : @{$summary{$_}} \n" foreach ( 'a', 'b' );
# both methods have this output summary
# char a : 3 3 2 2 3
# char b : 2 2 3 3 2
__DATA__
aaaaa
bbbbb
aabba
bbbbb
aaaaa
答案 0 :(得分:1)
根据数据的形成方式,method2可能比方法1更快或更慢。
但是一个很大的区别就是使用unpack而不是split。
use strict;
use warnings;
my ( %summary, %counthash ); # perl 5.8.9
sub method1 {
print "method1\n";
my @l= <DATA>;
for my $t(1..1000000) {
foreach (@l) {
my @c = split( // , $_ );
++$summary{ $c[$_] }[$_] foreach ( 0 .. $#c );
}
} # wend
} ## end sub method1
sub method2 {
print "method2\n";
++$counthash{$_} while (<DATA>); # slurpsum the whole file
for my $t(1..1000000) {
foreach my $str ( keys %counthash ) {
my $n = $counthash{$str};
my $i = 0;
$summary{ $_ }[$i++] += $n foreach ( unpack("c*",$str) );
}
}
} ## end sub method2
# MAINLINE
#method1();
method2();
print "char $_ : ". join (" ", @{$summary{ord($_)}}). " \n"
foreach ( 'a', 'b' );
# both methods have this output summary
# char a : 3 3 2 2 3
# char b : 2 2 3 3 2
__DATA__
aaaaa
bbbbb
aabba
bbbbb
aaaaa
跑得快得多。 (6而不是我电脑上的7.x秒)