Perl中来自同一输入文本文件的两个不一致的哈希值

时间:2014-09-08 14:33:10

标签: perl text hash

我创建了一个哈希,列出了文本文件中的每个唯一单词以及每个单词出现的次数。此哈希的结果输出表明它已正确读取整个文件。

但是,后来解析同一文件中文本的努力似乎只捕获了一些内容。

出于说明的目的,第二个散列被设计为从infile中捕获每个单词作为散列值,并且该单词在文档中作为散列键的相对排序仅捕获文档中所有单词的一小部分。

有关这种现象的原因的任何见解?

#!/usr/bin/perl

use strict;
use warnings;

my $path = "U:/Perl";
chdir($path) or die "Cant chdir to $path $!";

# Starting off computing a simple word count for each word in the 10-K.

my %hash;
my $word;
my %words;

while (<>) {
   my @words = split;

   # Here creating an index of each word in the 10-K and the number of times
   # it appears. This hash works correctly.

   foreach my $i (0 .. $#words) {
      my $word = $words[$i];
      ++$hash{$word};

      # Here trying to create a hash where each word from the infile is a value,
      # and the word's order in the doc is the key.

      $words{$i} = $word;
   }
}

# The code below simply sorts each hash and prints it to an external file.

my @keys = sort { "\L$a" <=> "\L$b" } keys %words;

open(my $fh2, '>', 'report2.txt');
foreach (@keys) {
   print $fh2 "$_ \t $words{$_}\n ";
}
close $fh2;

@keys = sort {
   "\L$hash{$a}" <=> "\L$hash{$b}" or
   "\L$a"        cmp "\L$b"
} keys %hash;

open(my $fh3, '>', 'report3.txt');
foreach (@keys) {
   print $fh3 "$_ \t $hash{$_}\n ";
}
close $fh3;

1 个答案:

答案 0 :(得分:1)

我认为你在谈论%words哈希?您通过每行上每个单词的位置来键入哈希值,因此它只会包含与文件中最长行相同的条目。

处理此数据时

a b c d e f
g h i j k
l m n o
p q r
s t
u

您的程序将使用21个元素构建%hash,其中键au,所有值均为1,因为它们都不同。

但是散列%words将有六个元素 - 最长行中的单词数 - 并且这些值将被行中该位置的 last 字覆盖。所以你的哈希看起来像

{ 0 => 'u', 1 => 't', 2 => 'r', 3 => 'o', 4 => 'k', 5 => 'f' }

作为该行第一个位置的最后一个单词是u,第二个位置的最后一个单词是t等。

当然,您不希望在整个文件中使用哈希索引单词?那将是一个数组


<强>更新

感谢您解释您的意图。我不认为将文件中的所有单词逐个放入哈希值可以帮助您计算所有独特的六字序列。

在任何情况下,使用1N的数字键,其中N是文件中的字数,是滥用哈希值,而且我在上面暗示了你的内容真正想要的是一个意味着的数组,用整数索引。

我认为你应该保留一个包含当前六字序列的数组。如果您将每个单词添加到数组的末尾并从头开始删除它,那么它将始终保存文件中最近的六个单词。

这样的事,也许是

use strict;
use warnings;

my @sequence;
my %sequences;

while (<DATA>) {
   for (split) {
     push @sequence, $_;
     if (@sequence >= 6) {
        shift @sequence while @sequence > 6;
        ++$sequences{"@sequence"};
     }
   }
}

use Data::Dump;
dd \%sequences;

__DATA__
a b c d e f
g h i j k
l m n o
p q r
s t
u

<强>输出

{
  "a b c d e f" => 1,
  "b c d e f g" => 1,
  "c d e f g h" => 1,
  "d e f g h i" => 1,
  "e f g h i j" => 1,
  "f g h i j k" => 1,
  "g h i j k l" => 1,
  "h i j k l m" => 1,
  "i j k l m n" => 1,
  "j k l m n o" => 1,
  "k l m n o p" => 1,
  "l m n o p q" => 1,
  "m n o p q r" => 1,
  "n o p q r s" => 1,
  "o p q r s t" => 1,
  "p q r s t u" => 1,
}