0

私はperlを初めて使用し、tsvからハッシュのハッシュを構築しようとしています。私の現在のプロセスは、ファイルを読み込んでハッシュを作成し、それを別のハッシュに挿入することです。

   my %hoh = ();
   while (my $line = <$tsv>) 
   {
      chomp $line;
      my %hash;
      my @data = split "\t", $line;

      my $id;
      my $iter = each_array(@columns, @data);

      while(my($k, $v) = $iter->())
      {
         $hash{$k} = $v;
         if($k eq 'Id')
         {
            $id = $v;   
         }
      }

      $hoh{$id} = %hash;
   }
   print "dump: ", Dumper(%hoh);

これは以下を出力します:

dump
$VAR1 = '1234567890';
$VAR2 = '17/32';
$VAR3 = '1234567891';
$VAR4 = '17/32';
.....

私が期待するものの代わりに:

dump
{
   '1234567890' => { 
                    'k1' => 'v1',
                    'k2' => 'v2',
                    'k3' => 'v3',
                    'k4' => 'v4',
                    'id' => '1234567890'
                   },
   '1234567891' => { 
                    'k1' => 'v1',
                    'k2' => 'v2',
                    'k3' => 'v3',
                    'k4' => 'v4',
                    'id' => '1234567891'
                   },
     ........
};

$hoh{$id} = %hash;私の限られた理解は、 %hash への参照に挿入するときですか? 私は何を間違っていますか?また、列とデータ配列をキー、値のペアとして %hash オブジェクトに使用するより簡潔な方法はありますか?

-前もってありがとう、ニル

4

4 に答える 4

2

参照を取得するには、次を使用する必要があります\

$hoh{$id} = \%hash;

%hashそれへの参照ではなく、ハッシュです。スカラー コンテキストでは、文字列X/Ywre を返します。X は使用されたバケットの数で、Y はハッシュ内のすべてのバケットの数です (つまり、何も役に立ちません)。

于 2013-07-19T20:04:19.607 に答える
2

ハッシュ変数への参照を取得するには、使用する必要があります\%hash(チョロバが言ったように)。

列に値を割り当てるより簡潔な方法は、次のようにハッシュ スライスに割り当てることです。

my %hoh = ();
while (my $line = <$tsv>) 
{
   chomp $line;
   my %hash;
   @hash{@columns} = split "\t", $line;
   $hoh{$hash{Id}} = \%hash;
}
print "dump: ", Dumper(\%hoh);

ハッシュ スライス ( ) は、基本的に、最大で何列も@hash{@columns}あるのと同じことを意味します。($hash{$columns[0]}, $hash{$columns[1]}, $hash{$columns[2]}, ...)それに割り当てることで、最初の値を からsplit$hash{$columns[0]}、2 番目の値を$hash{$columns[1]}に、というように割り当てます。while ... $iter明示的なループがないだけで、ループとまったく同じことを行います(そして、を抽出しません$id)。

$kそれぞれを'Id'ループ内で比較する必要はありません。通常のフィールドとしてハッシュに保存し、後で$hash{Id}. (余談: あなたの列ヘッダーIdまたはid?Idループで使用しますがid、期待される出力で使用します。)

個々のエントリにフィールドを保持したくない場合は、 deleteIdを使用できます(ハッシュからキーを削除し、値を返します)。

$hoh{delete $hash{Id}} = \%hash;
于 2013-07-19T21:16:23.837 に答える
1

Perl に含まれているドキュメントを参照してください。コマンドperldocは非常に便利です。Perldoc Web ページも参照できます。

チュートリアルの 1 つは、 Perl リファレンスに関するチュートリアルです。これらはすべて、多くの質問を明確にし、参照と逆参照について説明するのに役立ちます。

また、CPAN を参照することをお勧めします。これは、多くのさまざまなタスクを実行できるさまざまな Perl モジュールのアーカイブです。Text::CSVを見てください。このモジュールはまさにあなたが望むことを行います.「CSV」と書かれていますが、タブ区切りのファイルでも動作します.

参照しようとしているハッシュの前にスラッシュを入れ忘れました。あなたが持っている:

$hoh{$id} = %hash;

おそらく欲しい:

$hoh{$id} = \%hash;

また、ハッシュを実行するData::Dumper場合は、ハッシュへの参照に対して実行する必要があります。内部的には、Data::Dumper ダンプが行われると、ハッシュと配列は同様の構造を持ちます。

あなたが持っている:

 print "dump: ", Dumper(%hoh);

あなたが持っている必要があります:

 print "dump: ", Dumper( \%hoh );

プログラムでの私の試み:

#! /usr/bin/env perl
#
use warnings;
use strict;
use autodie;
use feature qw(say);
use Data::Dumper;

use constant {
    FILE    => "test.txt",
};

open my $fh, "<", FILE;

#
# First line with headers
#

my $line = <$fh>;
chomp $line;
my @headers = split /\t/, $line;
my %hash_of_hashes;

#
# Rest of file
#
while ( my $line = <$fh> ) {
    chomp $line;
    my %line_hash;
    my @values = split /\t/, $line;
    for my $index ( ( 0..$#values ) ) {
        $line_hash{ $headers[$index] } = $values[ $index ];
    }
    $hash_of_hashes{ $line_hash{id} } = \%line_hash;
}

say Dumper \%hash_of_hashes;
于 2013-07-19T21:20:06.483 に答える
0

変数がスコープから外れる前の最後の行で変数への参照を保存する場合にのみ、変数への参照を保存する必要があります。スクリプトでは%hash、while ループ内で宣言するため、このステートメントをループの最後に配置しても安全です。

$hoh{$id} = \%hash;

最後のステートメントでない場合 (または安全かどうかわからない場合)、変数の内容を保持する匿名構造を作成します。

$hoh{$id} = { %hash };

これにより のコピーが作成されますが%hash、これは処理が遅くなりますが、それ以降に変更を加えても、保存した内容には影響しません。

于 2013-07-19T23:34:11.993 に答える