我正在尝试使用目录中所有文本文件中的单词填充数组的哈希值。单词用作键,而文件名用作与键关联的标量值。
我正在使用数组哈希,因为一个单词可能很容易在另一个文本文件中重复。我想填写哈希;那么我想用关键词来搜索哪些文件包含一些给定的关键词。
我的代码摘录:
# 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";
}
}
似乎我可能没有正确地填充我的哈希(或者我只是不知道如何打印数组的哈希)。此外,我的匹配文件不正确。任何关于我做错的帮助都将不胜感激!谢谢!
答案 0 :(得分:1)
你缺少的是perl中没有任何像数组哈希这样的东西。或者一系列哈希。数组和散列都只能包含一个值。
他们的方式perl&#39;做&#39;多维是通过参考:
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";
}
}
(为了清晰起见,我已经使它变得比它需要的更冗长了 - 你可以进一步减少它)。
我还会提供一些辅助建议:
strict
和warnings
。它们对于编写好的代码非常重要。 不要那样使用open
。请尝试改为:
open ( my $file, "<", $filename ) or die $!;
while ( <$file> ) { ... }
我更喜欢glob
到readdir
和grep
,因为您正在做的方法之一就是所有open
都会失败,除非$directory
也是当前工作目录。 (您需要添加文件名的路径)。 :
foreach my $filename ( glob "$directory/*.txt" ) { ... }
split(' ');
很好,但它与split;
相同。选择您认为最具可读性的。
您实际上不需要做my @words = split;
foreach my $word ( split ) { ...
答案 1 :(得分:0)
你很接近,只需要在每个哈希键上展开
# 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";
}
}