2012-11-27 44 views
1

我有2个哈希 - >%a%b。 哈希%atemp.txt加速foreach循环中的perl哈希和更好的算法

my %a = map{ 
    my $short = substr($_,12); 
    $count++ => {$short => $_}; 
    } @a; 

my %b = map { 
    $_ => $_; 
    } @b; 

%a = (
    '1' => {'We go lunch' => 'We go lunch 9 pm'}, 
    '2' => {'We go break' => 'We go break 8 pm'}, 
    '3' => {'We go lunchy' => 'We go lunchy 8 pm'} 
); 

%b = (
    'We go lunch' => 'We go lunch', 
    'We go break' => 'We go break', 
    'We go lunchy' => 'We go lunchy' 
); 

foreach my $key (keys %a){ 
    foreach my $key2 (keys %{$a{$key}}){ 
     if(exists $b{$key2}){ 
     delete $a{$key}{$key2}; 
     delete $a{$key}; 
    } 
    } 
} 

my @another; 
foreach my $key (sort {$a<=>$b} keys %a) { 
    foreach my $key2 (keys %{$a{$key}}){ 
     $another[$count] = $a{$key}{$key2}; 
     $count++; 
    } 
} 

我怎么能加快呢?我的哈希是不是很奇怪?输入@anothertemp.txt中的25144行文字需要30秒。

是否需要为散列散列%a? 原因是我想要删除%a中的任何%b{$key}值。 我还在学习Perl,如果你们有更好的方式来做这件事,非常感谢,可能使用map和grep?和更好的算法?

以前的解决方法

,如果你看到每一个@b比每@a串短,但仍@a内。我曾尝试使用

foreach (@b) { 
my $source = $_; 
@another = grep !(/$source/i), @a;} 

但仍不起作用。我很困惑,于是把这个哈希散列写入%a,并且从@b写出哈希%b只是为了摆脱@a中@b的每个实例值。它出现怪异的散列。笑

+0

你为什么要设置%两次? – ikegami

+0

原因是在“以前的解决方法” – momokjaaaaa

+0

不是不是。它说你从@b制作%b,但你不是。 (好吧,你这样做,但是你完成了所有的工作。) – ikegami

回答

2

有几个未知数这里 - 如何建立%b例如。 否则,一些意见:

,您应该使用另一个阵列,而不是%a

my @c = map{ 
    { "".substr($_,12) => $_} 
    } @a; 

如果你已经有%b定义,可以通过进一步优化它:

my @another = grep !exists $b{ substr($_,12) }, @a; 

希望这帮助

另外,别忘了总是use strict;use warnings;在您的程序开始。

说明:

你的代码把一切都在%a,穿越它,并消除了什么应该不应该存在。 我想你可以简单地grep并保持在一个数组中只有预期的结果。

优化的代码应该变成:

use strict; 
use warning; 

my %b = (
    'We go lunch' => 'We go lunch', 
    'We go break' => 'We go break', 
    'We go lunch' => 'We go lunch' 
); 

#add code that initially fills @a 

my @another = grep { !exists $b{ substr($_,12) } } @a; 
+0

我在这之前做了这个grep,但无济于事,因为@a不像@b(之前的代码)那样是字符,所以一切都在@另一个。也许我的例子是不正确的。我现在改了它。 – momokjaaaaa

1

看来你很困惑。首先,substr $_, 12回报所有字符字符串中的第十二后,因此不会造成你说的它的数据结构。其次,使用的是散列%a作为阵列阵列的散列,作为密钥,而不在序列中的间隙整数,并且要存储的值是一个简单的字符串对。

对我们来说最大的问题是,在这一切中你都没有解释你的目标

它看起来像是最后的数组@another包含temp.txt的所有行,它们不以@b中的任何字符串开头。这是对的吗?

我将通过从阵列@b构建一个正则表达式,以及检查从文件每行我读它这样做。

此程序演示。我已经改名阵列@b@exclude因为前者是一个可怕的一个变量。正则表达式是由阵列的每个元件之前与^在字符串的开头以锚定正则表达式,以及附加\b迫使字边界(这样,例如,lunch不匹配lunchy)构建的。然后所有的元件使用一起|交替操作,导致在与@exclude的线的任何开头的字符串匹配正则表达式接合。

之后,读取文件很简单,按照正则表达式检查每行,然后将那些不匹配的行推送到@another

需要注意的是,因为它的立场,程序从DATA文件句柄读取,这样我可以包括在源一些测试数据。您应该通过取消注释open行并删除行my $fh = *DATA来更改它。

use strict; 
use warnings; 

#open my $fh, '<', 'temp.txt' or die $!; 
my $fh = *DATA; 

my @exclude = (
    'We go lunch', 
    'We go lunchy', 
    'We go break', 
); 

my $exclude_re = join '|', map "^$_\\b", @exclude; 

my @another; 
while (my $line = <$fh>) { 
    chomp $line; 
    push @another, $line unless $line =~ $exclude_re; 
} 

print "$_\n" for @another; 

__DATA__ 
We go breakfast 6 am 
We go lunch 9 pm 
We go break 8 pm 
We go lunchy 8 pm 
We go supper 7 pm 

输出

We go breakfast 6 am 
We go supper 7 pm