散列表中的Perl脚本搜索
我编写了一个Perl脚本,它有两个输入文件:散列表中的Perl脚本搜索,perl,hashtable,Perl,Hashtable,我编写了一个Perl脚本,它有两个输入文件: 第一个文件的每一行都有一个短语,然后括号之间有一个值。这里有一个例子: hello all (0.5) hi all (0.63) good bye all (0.09) 第二个文件有一个规则列表。例如: hello all -> salut (0.5) hello all -> salut à tous (0.5) hi all -> salut (0.63) good bye all -> au revoir (0.0
hello all (0.5)
hi all (0.63)
good bye all (0.09)
hello all -> salut (0.5)
hello all -> salut à tous (0.5)
hi all -> salut (0.63)
good bye all -> au revoir (0.09)
good bye -> au revoir (0.09)
hello all
),它将检查该短语是否存在于第一个文件中(在我们的示例中可以找到)
如果存在,则将整行hello all->salt(0.5)
写入输出。
因此,在本例中,输出文件应为:
hello all -> salut (0.5)
hello all -> salut à tous (0.5)
hi all -> > salut (0.63)
good bye all -> au revoir (0.09)
我的想法是将第一个文件的所有内容放入一个哈希表中。
为此,我的脚本如下:
#!/usr/bin/perl
use warnings;
my $vocabFile = "file1.txt";
my %hashFR =();
open my $fh_infile, '<', $InFile or die "Can't open $InFile\n";
while ( my $Ligne = <$fh_infile> ) {
if ( $Ligne =~ /(/ ) {
my ($cle, $valeur) = split /(/, $Ligne;
say $cle;
$h{$cle} = $valeur;
}
}
#/usr/bin/perl
使用警告;
my$vocabFile=“file1.txt”;
我的%hashFR=();
打开我的$fh_infle,'
干杯
干杯 您需要使用严格的。这将导致程序在遇到未声明的变量时失败,如$infle
(我假设您打算使用$vocabFile
)。我将忽略您发布的代码中的这些类型的问题,因为一旦启用strict,您可以自己修复它们
首先,现有代码存在两个逻辑问题。实际上,您似乎并没有使用存储为哈希值的括号中的数字,但如果您确实想使用它们,您可能应该去掉尾随的)
:
接下来,在使用字符串作为散列键之前去掉前导和尾随空格。您可能认为“foo”
和“foo”
是同一个词,但Perl不是
$cle =~ s/^\s+//;
$cle =~ s/\s+$//;
现在,你已经完成了大部分工作。显然,您已经知道如何读取文件、如何使用split
、以及如何使用散列。你只需要把这些放在一起。读取第二个文件:
open my $fh2, "<", "file2" or die "Can't open file2: $!";
while (<$fh2>) {
chomp;
…从键中去掉前导空格和尾随空格
$left =~ s/^\s+//;
$left =~ s/\s+$//;
…如果散列中存在密钥,则打印整行
print $_, "\n" if exists $hash{$left};
…处理完文件句柄后,不要忘记关闭它
close $fh2;
(尽管正如阿蒙所指出的,这并不是绝对必要的,特别是因为我们是在阅读而不是写作。这个话题处理得很好。)你需要使用strict
。这将导致程序在遇到未声明的变量时失败,如$infle
(我假设您打算使用$vocabFile
)。我将忽略您发布的代码中的这些类型的问题,因为一旦启用strict,您可以自己修复它们
首先,现有代码存在两个逻辑问题。实际上,您似乎并没有使用存储为哈希值的括号中的数字,但如果您确实想使用它们,您可能应该去掉尾随的)
:
接下来,在使用字符串作为散列键之前去掉前导和尾随空格。您可能认为“foo”
和“foo”
是同一个词,但Perl不是
$cle =~ s/^\s+//;
$cle =~ s/\s+$//;
现在,你已经完成了大部分工作。显然,您已经知道如何读取文件、如何使用split
、以及如何使用散列。你只需要把这些放在一起。读取第二个文件:
open my $fh2, "<", "file2" or die "Can't open file2: $!";
while (<$fh2>) {
chomp;
…从键中去掉前导空格和尾随空格
$left =~ s/^\s+//;
$left =~ s/\s+$//;
…如果散列中存在密钥,则打印整行
print $_, "\n" if exists $hash{$left};
…处理完文件句柄后,不要忘记关闭它
close $fh2;
(虽然正如阿蒙所指出的,这并不是绝对必要的,尤其是因为我们在读而不是写。这个主题处理得很好。)这可以通过直接从第一个文件的内容创建一个散列,然后读取第二个文件的每一行来非常直接地完成,检查哈希以查看是否应打印它
use strict;
use warnings;
use autodie;
my %permitted = do {
open my $fh, '<', 'f1.txt';
map { /(.+?)\s+\(/, 1 } <$fh>;
};
open my $fh, '<', 'f2.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
print if $permitted{$phrase};
}
通过直接从第一个文件的内容创建一个散列,然后读取第二个文件的每一行,检查散列是否应该打印,可以非常直接地完成这项工作
use strict;
use warnings;
use autodie;
my %permitted = do {
open my $fh, '<', 'f1.txt';
map { /(.+?)\s+\(/, 1 } <$fh>;
};
open my $fh, '<', 'f2.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
print if $permitted{$phrase};
}
这是一个很好的答案,但是很好的答案也解释了他们在做什么,而不是转储代码。您的代码存在一些问题。第一,您没有对open
使用任何错误处理。我建议使用autodie
作为补救措施。第二,你的代码效率很低。您可以直接打印该行,而不是push@result,
@阿蒙-显然是的!它不是完美的,但也不是“生产”代码。这只是一个例子。我的意图是概述解决方案,重点是检索数据。@amon-还有一件事-如果我的代码中有任何不清楚的地方,请随时询问!我认为这几乎是自我记录;)这是一个很好的答案,但是很好的答案也解释了他们在做什么,而不是转储代码。您的代码存在一些问题。第一,您没有对open
使用任何错误处理。我建议使用autodie
作为补救措施。第二,你的代码效率很低。您可以直接打印该行,而不是push@result,
@阿蒙-显然是的!它不是完美的,但也不是“生产”代码。这只是一个例子。我的意图是概述解决方案,重点是检索数据。@amon-还有一件事-如果我的代码中有任何不清楚的地方,请随时询问!我认为这几乎是自我记录;)这是一个令人难以置信的好答案+一路走来!吹毛求疵:关闭不是必要的,而且die代码>是一个语法错误;-)您的意思是使用autodie
或die“无法打开文件2:$!”
@amon谢谢,并已修复。这就是我使用答案框作为编译器得到的结果;)这是一个令人难以置信的好答案+一路走来!吹毛求疵:关闭不是必要的,而且die代码>是一个语法错误;-)您的意思是使用autodie
或die“无法打开文件2:$!”
@amon谢谢,并已修复。这就是我使用答案框作为编译器得到的结果;)谢谢你的回复。我现在用的是Borodin的