2

タブ区切りファイル(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 found\n";
     while (<LIST1>) {
          ($tmpvar1, $tmpvar2) = split(/\t/, $_);
          $hashname{$tmpvar1} = $tmpvar2;
     }
close(LIST1);
4

4 に答える 4

2

データには複数の値を持つキーが含まれているため、データ ファイルが実際にそうであると仮定すると、キーが配列に関連付けられている配列のハッシュ (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: aaa1 with val: ccc2 found.

お役に立てれば!

于 2012-07-20T06:35:57.137 に答える
1

まず、あなたの質問は Keys/Valuesペアの重複に固有のものであると解釈します。これは少し厄介です。通常の質問はキーをテストすることですが、キーと値の両方を新しいキーを生成する関数への入力にすることで、キー値を実行できます。

タブ区切りの CSV を使用しているだけの場合は、Text::CSVを使用してください。これは正しく行われ、最も複雑なケースがカバーされているので安心してください! Text::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

それを理解すれば、残りの演習も簡単です。私は、キーと値をsha1'edし、2つを連結し、それによってハッシュにインデックスを付ける非常に単純なアルゴリズムを使用します。これにより、狡猾な衝突の試みが排除されますが、タスクには必要ない場合があります。お気軽にご質問ください。

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
于 2012-07-20T05:10:33.093 に答える
0

キーが重複しているため、入力ファイルは 3 つの要素のハッシュのみになります。実際には、そのような状況に対処する必要がありますが、この場合は入力ファイルを変更します。

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 found\n";
   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";
       }
}
于 2012-07-20T03:46:45.413 に答える
0

最初に Perl に出会ったときは、 pragma を使用しますuse strict;

あなたのファイルが構成されていることに気付きました

aaa1  aaa2
aaa1  bbb2

ファイルの処理中'aaa1' => 'bbb2'、Perl はハッシュに一意のキーを持っているため、ハッシュは 1 つのキーのみを格納します。

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;
于 2012-07-20T03:46:57.147 に答える