2

我想看看我的数组中是否有重复的项目,有超过 16.000 个,所以会自动化它可能有其他方法,但我从这个开始,嗯,除非有一个简单的命令,否则我想完成它。我正在做的是从一个数组移动并推送到另一个数组,这样,检查目标数组以查看它是否“在数组中”(就像 PHP 中有这样的命令)。

所以,我得到了这个子例程,它适用于文字,但不适用于变量。这是因为'eq'或我应该需要的任何东西。'sourcefile' 将包含目标数组的一个或多个单词。

// Here I just fetch my file


    $listamails = <STDIN>;
    # Remove the newlines filename
    chomp $listamails;
    # open the file, or exit
    unless ( open(MAILS, $listamails) ) {

    print "Cannot open file \"$listamails\"\n\n";
    exit;
    }
    # Read the list of mails from the file, and store it
    # into the array variable @sourcefile
    @sourcefile = <MAILS>;
    # Close the handle - we've read all the data into @sourcefile now.
    close MAILS;


    my @destination = ('hi', 'bye');

    sub in_array
    {
       my ($destination,$search_for) = @_;
       return grep {$search_for eq $_} @$destination;
    }

    for($i = 0; $i <=100; $i ++)

    {
      $elemento = shift @sourcefile;
      if(in_array(\@destination, $elemento))
      {
        print  "it is";
      }
      else
      {
        print "it aint there";
      }
    }

好吧,如果我没有在其中包含 $elemento,而是在其中放置了一个“hi”,它确实可以工作,并且我还打印了 $elemento 的值,它也是“hi”,但是当我放置变量时,它不起作用,并且那是因为'eq',但我不知道还能放什么。如果我输入 == 它会抱怨 'hi' 不是数值。

4

4 回答 4

4

当您想要不同的值时,请考虑哈希。

my %seen;
@seen{ @array } = (); 

if (keys %seen == @array) {
    print "\@array has no duplicate values\n";
}
于 2012-06-30T13:39:54.090 回答
2

不清楚你想要什么。如果您的第一句话是唯一重要的(“我想看看我的数组中是否有重复的项目”),那么您可以使用:

my %seen;
if (grep ++$seen{$_} >= 2, @array) {
   say "Has duplicates";
}

你说你有一个大数组,所以一旦找到重复项就停止可能会更快。

my %seen;
for (@array) {
   if (++$seen{$_} == 2) {
      say "Has duplicates";
      last;
   }
}
于 2012-06-30T16:39:11.747 回答
1

正如eugene y所说,哈希绝对是这里的必经之路。这是您发布到基于哈希的方法的代码的直接翻译(在此过程中添加了更多的 Perlishness):

my @destination = ('hi', 'bye');
my %in_array = map { $_ => 1 } @destination;

for my $i (0 .. 100) {
  $elemento = shift @sourcefile;
  if(exists $in_array{$elemento})
  {
    print  "it is";
  }
  else
  {
    print "it aint there";
  }
}

此外,如果您的意思是检查 的所有元素@sourcefile(而不是测试前 101 个元素)@destination,您应该将该for行替换为

while (@sourcefile) {

另外,不要忘记chomp从文件中读取的任何值!从文件中读取的行在它们的末尾有一个换行符(\r\n\n在初始问题的评论中提到),这将导致两者eq和哈希查找都报告否则匹配的值是不同的。这很可能是您的代码一开始就无法正常工作的原因,而改用 usesort或 hash 也无法解决这个问题。首先chomp您的输入使其工作,然后使用sort或散列以使其高效。

于 2012-06-30T15:11:32.233 回答
1

顺便说一句,在大量项目中查找重复项时,使用基于排序的策略要快得多。对项目进行排序后,所有重复项将彼此相邻,因此要判断某项是否重复,您只需将其与前一个进行比较即可:

@sorted = sort @sourcefile;
for (my $i = 1; $i < @sorted; ++$i) {   # Start at 1 because we'll check the previous one
    print "$sorted[$i] is a duplicate!\n" if $sorted[$i] eq $sorted[$i - 1];
}

如果有多个欺骗,这将打印多个欺骗消息,但您可以清理它。

于 2012-06-30T13:41:39.127 回答