加快foreach循环中的perl哈希和更好的算法

加快foreach循环中的perl哈希和更好的算法,perl,hash,foreach,Perl,Hash,Foreach,我有两个哈希->%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'

我有两个哈希->
%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++;
   }
}

但它仍然不起作用。我很困惑,因此在%a中出现了这个散列,并从@b中生成了散列%b,只是为了去掉@a中@b的每个实例值。结果是奇怪的杂烩。lol

这里有一些未知的东西-例如,
%b
是如何构建的。 除此之外,还有一些观察:

您应该使用另一个数组,而不是
%a

  my @c = map{
    { "".substr($_,12) => $_}
   } @a;
如果您已经定义了
%b
,您可以通过以下方式进一步优化它:

my @another = grep !exists $b{ substr($_,12) }, @a;
希望这有帮助

另外,不要忘了总是严格使用代码
使用警告在程序的开头

解释:

您的代码将所有内容放入
%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;

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

对我们来说,最大的问题是你没有解释你的目标

看起来是这样的:您希望最后得到一个数组
@另一个
,该数组包含
temp.txt
中的所有行,这些行不以
@b
中的任何字符串开头。是这样吗

我将通过从数组
@b
构建一个正则表达式,并在读取文件时检查文件中的每一行来实现

这个程序演示了。我已将数组
@b
重命名为
@exclude
,因为前者对于变量来说是一个糟糕的名称。正则表达式是通过在数组的每个元素前面加上
^
来构建的,以将正则表达式锚定在字符串的开头,并在
\b
后面加上
\b
来强制设置单词边界(例如,
sunch
sunchy
不匹配)。然后使用
|
交替运算符将所有元素连接在一起,生成一个正则表达式,该正则表达式匹配以
@exclude
中的任何行开头的字符串

在这之后,只需通读文件,对照正则表达式检查每一行,然后将不匹配的行推到另一行

请注意,目前程序从
数据
文件句柄读取数据,以便在源代码中包含一些测试数据。您应该通过取消注释
open
行,并删除行
my$fh=*DATA
来更改它

使用严格;
使用警告;

#打开我的$fh,'为什么要设置%a两次?原因是在“以前的解决方法”下,而不是它不是。上面说你是从@b中获得%b,但你不是。(好的,您可以,但您已完成擦除所有工作。)哈希%b未被擦除。我只删除了hash%aI在这之前做了这个grep,但没有用,因为@a和@b(以前的代码)不是一个字符接一个字符的,所以@other中的所有内容都是未定义的。也许我的例子不对。我现在改了。
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;