在perl中将一个tab分隔的文件读取为hash并进行搜索



我有一个制表符分隔的文件(inpFile.txt)作为

field1  field2
aaa1  aaa2
aaa1  bbb2
aaa1  ccc2 
ccc1  ddd2
eee2  aaa2

我想读取它并将其存储到哈希(hashname)中

一旦我的散列准备好了,我想搜索是否找到了($key,$value)对。例如,是否找到(eee2,aaa2)?

我是Perl的初学者,但我知道用Perl可以有效地完成这项工作,而且很容易。

我写了以下代码。你能再延长一点吗?

感谢

#!/usr/local/bin/perl
open (LIST1, "/inpFile.txt") || die "File not foundn";
     while (<LIST1>) {
          ($tmpvar1, $tmpvar2) = split(/t/, $_);
          $hashname{$tmpvar1} = $tmpvar2;
     }
close(LIST1);

由于您的数据包含具有多个值的键,并且假设数据文件中确实存在这种情况,因此您可以创建数组哈希(HoA),其中键与数组相关联:

use Modern::Perl;
my %hashname;
while (<DATA>) {
    my ( $key, $value ) = split;
    push @{ $hashname{$key} }, $value;
}
my $searchKey = 'aaa1';
my $searchVal = 'ccc2';
if ( defined $hashname{$searchKey}
    and $searchVal ~~ @{ $hashname{$searchKey} } )
{
    say "key: $searchKey with val: $searchVal found.";
}
else {
    say "key: $searchKey with val: $searchVal not found.";
}
__DATA__
aaa1  aaa2
aaa1  bbb2
aaa1  ccc2 
ccc1  ddd2
eee2  aaa2

搜索"key/value"对的方法是首先查看该键是否存在,然后使用智能匹配运算符查看该值是否存在于与该键关联的数组中。

输出:

key: aaa1 with val: ccc2 found.

希望这能有所帮助!

首先,我将您的问题解释为特定于键/值对上的重复。这有点尴尬——通常的问题只是测试键,但我们可以通过将键和值都作为生成新键的函数的输入来实现键值。

如果你只是使用一个标签分隔的CSV,请使用文本::CSV,并确保它做得正确,涵盖了最复杂的情况!安装文本::CSV_XS,使其速度也非常快。

use strict;
use warnings;
use Data::Dumper;
use Text::CSV;
use IO::Handle;
my $csv = Text::CSV->new({sep_char=>"t"});
my $fh = IO::Handle->new_from_fd( *DATA, 'r' );
while ( not $fh->eof ) {
  my $row = $csv->getline( $fh );
  warn Dumper $row;
}
__DATA__
aa1 aaa2
aaa1  bbb2
aaa1  ccc2 
ccc1  ddd2
eee2  aaa2

在你理解了这一点之后,剩下的练习也很简单。我使用了一个非常简单的算法,它将键和值连接起来,并以此为基础索引哈希。这消除了巧妙的碰撞尝试,但可能对您的任务没有必要。请随意提问。

use feature ':5.10';
use strict;
use warnings;
use Data::Dumper;
use Text::CSV;
use IO::Handle;
use Digest::SHA qw(sha1_hex);
my $csv = Text::CSV->new({sep_char=>"t"});
my $fh = IO::Handle->new_from_fd( *DATA, 'r' );
my ( %kv, %sha1_kv );
while ( not $fh->eof ) {
  my $row = $csv->getline( $fh );
  my ($k, $v) = @$row;
  my $sha1 = sha1_hex($k) . sha1_hex($v);
  if ( exists $sha1_kv{ $sha1 } ) {
    say "We have a hit (key/value dupe) for $sha1 [key: $k]";
  }
  else {
    $kv{ $k } = $v;
    $sha1_kv{ $sha1 } = $v;
  }
  warn Dumper $row;
}
__DATA__
aa1 aaa2
aa1 aaa2
aaa1  bbb2
aaa1  ccc2 
ccc1  ddd2
eee2  aaa2

首先,当您使用Perl时,请使用pragma use strict;

我注意到你的文件由组成

aaa1  aaa2
aaa1  bbb2

在处理我们的文件时,hash将只存储一个密钥'aaa1' => 'bbb2',因为Perl在hash中有唯一的密钥。

use strict;
open my $fh, '<', '/input_file.txt' 
    or die "Cant open file $!";
LINE:
while (my $line = <$fh>) {
    my ($key, $value) = split /t/, $line;
    next LINE if not $key;
    $hash{$key} = $value;
}
my $search_key   = 'eee2';
my $search_value = 'aaa2';
if ($hash{$search_key} eq $search_value) {
   print "Found key: $search_key and value: $search_value in hash /n";
}
close $fh;

YOU的输入文件将只产生三元素哈希,因为键是重复的。在现实生活中,你必须处理这种情况,但在这种情况下,我会更改你的输入文件:

aaa1    aaa2
bbb1    bbb2
ccc1    ccc2
ccc1    ddd2
eee2    aaa2

以下是对您的代码的一些增强:

#!/usr/local/bin/perl
#always use strict and warnings
use strict;
use warnings;
use Data::Dumper;
hash_test();
#Try to put your code in separate subs if possible 
sub hash_test {
   my %hashname = ();
   read_into_hash( %hashname );
   print Dumper( %hashname );    # Test your hash
   search_hash( %hashname, "eee2", "aaa2" );
}
sub read_into_hash {
   #Always declare variables
   my $list1;
   my $tmpvar1;
   my $tmpvar2;
   my $hash_ref = shift;
   my $lineno = 0;
   open( $list1, "<", "/inpFile.txt" ) or die "File not foundn";
   while (<$list1>) {
       $lineno++;
       chomp;    #delete new line character
       ( $tmpvar1, $tmpvar2 ) = split( /t/, $_ );
       if (defined $hash_ref->{$tmpvar1})
       {
         # adding lineno from file to avoid overwriting. I use '~' just in case
         # if your keys could include such character, use something else
         $tmpvar1 .= "~" . $lineno;
       }
       $hash_ref->{$tmpvar1} = $tmpvar2;
   }
   close($list1);
}
sub search_hash {
   my $hash_ref = shift;
   my $key      = shift;
   my $value    = shift;
   if (defined $hash_ref->{$key} && $hash_ref->{$key} =~ /^$value(~d+)*$/)
   {
           print "Found.n";
       }
}

最新更新