2015-06-23 103 views
1

我正在嘗試使用來自目錄中所有文本文件的單詞來填充數組的散列。單詞用作鍵,文件名用作與鍵相關聯的標量值。在Perl中填充和搜索數組的散列?

我正在使用數組的散列,因爲一個單詞可能很容易在另一個文本文件中重複。我想填寫散列表;那麼我想通過關鍵詞搜索來確定哪些文件包含一些給定的關鍵字。

我的代碼的摘錄:

# Search term(s). 
my @search_terms = ("random", "searches"); 

opendir(DIR, $directory) or die $!; 
@files = grep(/\.txt$/, readdir(DIR)) or die("you idiot"); 

# Create a hash table to store the words as keys and the file name. 
my %hash; 

# Go through the files, grab the words, and create hash table. 
foreach my $file(@files) { 
    open(FILE,"<$file") or die $!; 
    while(<FILE>){ 
     chomp; 
     my @words = split(' '); 
     # Store the key, value pairs for each file. 
     # Key is the word. 
     # Value is the file name. 
     foreach my $word(@words) { 
      push @{$hash{$word}}, $file; 
     } 
    } 
    close(FILE); 
} 

# Go through each search term. 
foreach my $match(@search_terms) { 
    # If a key exists in the hash table, then we have a matched result. 
    if($hash{$match}) { 
     # Print the file name (scalar value for word key). 
     print "$hash{$match} matched."; 
     print "\n"; 
    } 
} 

看來,也許我沒有正確填寫我的哈希(或者我只是不知道如何打印數組的哈希值)。另外,我的匹配對於文件不正確。任何幫助,我做錯了什麼將不勝感激!謝謝!

回答

1

你缺少的事情是,確實沒有任何這樣的東西在Perl陣列的哈希值。或一組哈希值。數組和哈希都只能包含一個值。

他們的方式perl的 '不' 多維通過引用:

my %hash; 
push (@{$hash{'fish'}}, "trout"); 

foreach my $key (keys %hash) { 
    print "$key $hash{$key}\n"; 
} 

這將打印(類似):

fish ARRAY(0x2d6ed4) 

這是因爲在$hash{$key}單個值是對該數組的引用。然後您需要取消引用才能訪問。

E.g.

print join ("\n", @{$hash{$key}}); 

例如。

Data::Dumper可以幫助你瞭解這是怎麼回事:

my %hash; 
push (@{$hash{'fish'}}, "trout"); 

print Dumper \%hash; 

打印:

$VAR1 = { 
      'fish' => [ 
         'trout' 
        ] 
     }; 

要回答你原來的問題 - 稍微改變你的foreach循環:

foreach my $match (@search_terms) { 
    # If a key exists in the hash table, then we have a matched result. 
    if($hash{$match}) { 
     # Print the file name (scalar value for word key). 
     # $hash{$match} is an array reference, so we need to de-reference: 
     my @matching_files = @{$hash{$match}}; 
     print "$match found in:\n"; 
     print join ("\n", @matching_files),"\n"; 
    } 
} 

(爲了清晰起見,我已經制作了一些比詳細的更詳細的信息 - 你可以減少i儘管如此)。

我也將提供一定的輔助建議:

  • 打開strictwarnings。它們對編寫好的代碼非常重要。
  • 不要使用那樣的open。嘗試改爲:

    open (my $file, "<", $filename) or die $!; 
    while (<$file>) { ... } 
    
  • 我喜歡globreaddirgrep,因爲你做了該方法的陷阱之一是,所有的open旨意失敗,除非$directory也是當前的工作目錄。 (你需要添加一個路徑到文件名)。 :

    foreach my $filename (glob "$directory/*.txt") { ... } 
    
  • split(' ');是好的,但它一樣split;。選擇你覺得最可讀的。

  • 你實際上並不需要做my @words = split;你可以只是做foreach my $word (split) { ...

0

你靠近,只需要在每個哈希鍵展開療法rray

# Go through each search term. 
foreach my $match(@search_terms) { 
    # If a key exists in the hash table, then we have a matched result. 
    if($hash{$match}) { 
     # Print the file name (scalar value for word key). 
     print "$hash{$match} matched in file(s) "; 
     foreach my $elem (@{"$hash{$match}}) { 
      print "$elem : " 
     } 
     print "\n"; 
    } 
}