1

我有 2 个哈希 -> %a%b. 哈希%a来自temp.txt

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++;
   }
}

我怎样才能加快速度?我的哈希值很奇怪吗?@another输出25144 行单词用时30 秒temp.txt

是否有必要对哈希进行哈希处理%a?原因是我希望删除任何%b{$key}值。%a如果你们有更好的方法来做这件事,我还在学习 Perl,非常感谢,可能使用 map 和 grep?和更好的算法?

以前的解决方法

如果您看到每个@b 都比每个@a 都短,但仍在@a 内。我曾尝试使用

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

但它仍然不起作用。我很困惑,因此在 %a 中出现了这个哈希值,并从 @b 中生成哈希 %b 只是为了摆脱 @a 中 @b 的每个实例值。结果是奇怪的哈希。哈哈

4

2 回答 2

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;
于 2012-11-27T07:52:46.977 回答
1

看来你很困惑。首先,substr $_, 12返回字符串中第 12 位之后的所有字符,因此不会创建您所说的数据结构。其次,您使用 hash of hashes%a作为arrays 的数组,因为键是序列中没有间隙的整数,而您存储的值是一个简单的字符串对。

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

它看起来是你想要结束的数组@another包含所有temp.txt不以任何字符串开头的行@b。这对吗?

我会通过从 array 构建正则表达式@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
于 2012-11-27T13:09:07.987 回答