散列表中的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

我编写了一个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.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的