Arrays Perl-构建数组数组会导致溢出

Arrays Perl-构建数组数组会导致溢出,arrays,perl,Arrays,Perl,我试图分析hashmap,寻找重复的值,并在数组中获取它们的键。这些数组将位于数组的数组中。顺便说一下,我是个新手。然而,当我启动它时,它从未停止运行。我错在哪里 while (($k,$v)=each %hashmap){ $hasduplicate = 0; delete $hashmap{$k}; @dups = (); while (($k1,$v1) = each %hashmap){ if ($v

我试图分析hashmap,寻找重复的值,并在数组中获取它们的键。这些数组将位于数组的数组中。顺便说一下,我是个新手。然而,当我启动它时,它从未停止运行。我错在哪里

while (($k,$v)=each %hashmap){
        $hasduplicate = 0;
        delete $hashmap{$k};
        @dups = ();
        while (($k1,$v1) = each %hashmap){
            if ($v1 eq $v) {
                $hasduplicate = 1;
                push @dups, $k1;
                delete $hashmap{$k1};
            }
        }
        if ($hasduplicate){
            push (@dups, $k);
            push @dupsarray, [@dups];}
}

在Perl中,每个哈希只有一个与其自身对齐的迭代器(请参阅)。因此,在调用
each
的循环中为相同的哈希运行
each
并不是按照您的想法进行的

如果要查看发生了什么,请尝试在外部循环的开始处添加以下行:

warn $k;
变量名前缺少几个美元符号。例如,您可能希望删除
$hashmap{$k}
,而不是
$hashmap{k}
,这相当于
$hashmap{'k'}

要输出数组数组,必须取消对内部数组的引用:

print map "@$_\n", @dupsarray;
顺便说一句,我会使用数组散列来解决您的任务。以下是方法:

my %dups;
while (my ($k, $v) = each %hashmap) {
    push @{ $dups{$v} }, $k;
}

for my $k (grep @{ $dups{$_} } > 1, keys %dups) {
    print "$k: @{ $dups{$k} }\n";
}

在Perl中,每个哈希只有一个与其自身对齐的迭代器(请参阅)。因此,在调用
each
的循环中为相同的哈希运行
each
并不是按照您的想法进行的

如果要查看发生了什么,请尝试在外部循环的开始处添加以下行:

warn $k;
变量名前缺少几个美元符号。例如,您可能希望删除
$hashmap{$k}
,而不是
$hashmap{k}
,这相当于
$hashmap{'k'}

要输出数组数组,必须取消对内部数组的引用:

print map "@$_\n", @dupsarray;
顺便说一句,我会使用数组散列来解决您的任务。以下是方法:

my %dups;
while (my ($k, $v) = each %hashmap) {
    push @{ $dups{$v} }, $k;
}

for my $k (grep @{ $dups{$_} } > 1, keys %dups) {
    print "$k: @{ $dups{$k} }\n";
}

问题是每个散列只能有一个
序列,因为只有一个索引来跟踪下一个键/值对

此外,您在一些地方使用了
k
k1
,您的意思是
$k
$k1
。在每个Perl程序的顶部,必须始终
使用strict
使用warnings
。这会提醒你注意这个问题

您可以通过对我的$k1(键%hashmap){…}
使用
来解决这个问题。这将创建一个单独的键列表,依次分配给
$k1
,这样就不会多次使用迭代器

对代码的修改符合我的要求

use strict;
use warnings;

my %hashmap = (
  a => 'a',
  b => 'b',
  c => 'a',
  d => 'c',
);

my @dupsarray;

while (my ($k, $v) = each %hashmap) {
  my $hasduplicate = 0;
  delete $hashmap{$k};
  my @dups;

  for my $k1 (keys %hashmap) {
    my $v1 = $hashmap{$k1};
    if ($v1 eq $v) {
      $hasduplicate = 1;
      push @dups, $k1;
      delete $hashmap{$k1};
    }
  }

  if ($hasduplicate) {
    push(@dups, $k);
    push @dupsarray, [@dups];
  }

}


use Data::Dump;
dd \@dupsarray;
输出

[["a", "c"]]
[["c", "a"]]
一个更简单的方法是创建一个反向散列,其中交换原始散列的键和值。然后只需选择包含多个元素的反转哈希值。本程序演示

use strict;
use warnings;

my %hashmap = (
  a => 'a',
  b => 'b',
  c => 'a',
  d => 'c',
);

my @dupsarray = do {
  my %inverted;
  while (my ($k, $v) = each %hashmap) {
    push @{ $inverted{$v} }, $k;
  }
  grep { @$_ > 1 } values %inverted;
};


use Data::Dump;
dd \@dupsarray;
输出

[["a", "c"]]
[["c", "a"]]

问题是每个散列只能有一个
序列,因为只有一个索引来跟踪下一个键/值对

此外,您在一些地方使用了
k
k1
,您的意思是
$k
$k1
。在每个Perl程序的顶部,必须始终
使用strict
使用warnings
。这会提醒你注意这个问题

您可以通过对我的$k1(键%hashmap){…}
使用
来解决这个问题。这将创建一个单独的键列表,依次分配给
$k1
,这样就不会多次使用迭代器

对代码的修改符合我的要求

use strict;
use warnings;

my %hashmap = (
  a => 'a',
  b => 'b',
  c => 'a',
  d => 'c',
);

my @dupsarray;

while (my ($k, $v) = each %hashmap) {
  my $hasduplicate = 0;
  delete $hashmap{$k};
  my @dups;

  for my $k1 (keys %hashmap) {
    my $v1 = $hashmap{$k1};
    if ($v1 eq $v) {
      $hasduplicate = 1;
      push @dups, $k1;
      delete $hashmap{$k1};
    }
  }

  if ($hasduplicate) {
    push(@dups, $k);
    push @dupsarray, [@dups];
  }

}


use Data::Dump;
dd \@dupsarray;
输出

[["a", "c"]]
[["c", "a"]]
一个更简单的方法是创建一个反向散列,其中交换原始散列的键和值。然后只需选择包含多个元素的反转哈希值。本程序演示

use strict;
use warnings;

my %hashmap = (
  a => 'a',
  b => 'b',
  c => 'a',
  d => 'c',
);

my @dupsarray = do {
  my %inverted;
  while (my ($k, $v) = each %hashmap) {
    push @{ $inverted{$v} }, $k;
  }
  grep { @$_ > 1 } values %inverted;
};


use Data::Dump;
dd \@dupsarray;
输出

[["a", "c"]]
[["c", "a"]]

循环内循环方法所用的时间与元素数量的平方成正比。底部的解决方案所花费的时间与散列中的元素数成比例。后者的可伸缩性要好得多。循环内循环方法所用的时间与元素数量的平方成正比。底部的解决方案所花费的时间与散列中的元素数成比例。后者的伸缩性要好得多。