0

これが他の場所で解決されている場合はお詫び申し上げます。探して探しました。

各チャンクの名前を左揃えにし、各名前の引数をインデントすることで、データのチャンクを分離する構成ファイルを使用しています (以下を__DATA__参照)。$hash{name}スカラー値を%hash{args}指すキーと、値の配列を指すキーを持つハッシュに各チャンクを格納するスクリプトを作成しました。各チャンクは独自のハッシュに格納されるため、ハッシュへの参照は匿名で配列に格納されます。最終的には、これらのハッシュを 1 つずつ取得して値を処理したいと考えていますが、配列の反復処理に問題があります。

各ハッシュに格納されている値を出力しようとすると、リスト コンテキストでその配列のハッシュ参照を取得しているように見えるため、%hash{args} が 3 つの要素を持つ配列への参照である場合、それは foreach ループの 3 倍になります。実行します。

そのループ内のコードを、その配列に吸い込んだハッシュ参照ごとに 1 回だけ実行するにはどうすればよいですか?

私の出力を確認すると、ネストされた配列参照を逆参照する必要があることは明らかですが、ループを正しくすることに固執しているため、まだそれに取り組むことができませんでした。多分解決策は両方を修正しますか?

見よ:

use strict;
use warnings;

my @array;
my %hash;
my ($name, $args);

while (my $line = <DATA>) {
    chomp($line);        
    if ($line !~ /^\s/) 
    {
        my ($key) = $line =~ /^\S+/g;
        $hash{name} = $key;
        print "Defined a name $key\n";
     } 
     else 
     {
        $line =~ s/^\s+//;
        push (@{ $hash{args} }, $line);
        print "Defined an arg $line\n";
     }
     push (@array, \%hash);
}

foreach my $i (@array)
{
    foreach my $h (keys %{$i}) 
    {
        print $h . "\t";
        print $i->{$h} . "\n";      

    }
}


__DATA__
Sports
    Basketball
    Tennis
    Boxing
Guys
    Tom
    Dick
    Harry

出力は次のとおりです。

Defined a name Sports
Defined an arg Basketball
Defined an arg Tennis
Defined an arg Boxing
Defined a name Guys
Defined an arg Tom
Defined an arg Dick
Defined an arg Harry
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
args    ARRAY(0x4a8e24)
name    Guys
4

2 に答える 2

1

あなたの問題:

データ構造を構築しているときに、いくつかの間違いを犯しました。

  • 常に$key同じ$hash{name}フィールドに新しいを割り当てます。以前の内容は上書きされます。最後の値が残りGuysます。
  • の参照を にプッシュし%hashます@array。参照は元のオブジェクトのすべての変更を反映するため、毎回同じ出力が得られます。

ソリューション:

別のデータ構造を使用してください;-)

データは次のように機能します。それぞれが値のリストを持つ一連の名前を持っています。セットは Perl のハッシュでモデル化されているため、1 つを使用します。

my %hash = ();

各エントリには、値を含む配列への参照が含まれます。最終的なデータ構造は次のようになります。

%hash = (
    Sports => ["Basketball", "Tennis", "Boxing"],
    Guys   => ["Tom", "Dick", "Harry"]
);

Data::Dumperモジュールを使用して、現在のデータ構造を調べることができます。

use Data::Dumper;
print Dumper (\%name); # has to be given references

このデータ構造を使用するには、コードに最小限の改善を加えるだけで済みます。

my %hash;
my $key;
while (my $line = <DATA>) {
    chomp $line;        
    if ($line =~ /^(\S+)/) {
        $key = $1;
        $hash{$key} = []; # this is the main difference
        print "Defined a name $key\n";
     } else {
        $line =~ s/^\s+//;
        push @{ $hash{$key} }, $line;
        print "Defined an arg $line\n";
     }
}

コーディング スタイルも少し変更しましたが、本質的に唯一の違いは、名前をハッシュキーとして使用することです。$keyすべての引数がどこに行くべきかを知るために、ループの外で最後に使用されたものを覚えています。

データ構造を出力したいeach場合、名前の順序が重要でない場合は関数を使用します。

while (my ($name, $arrayRef) = each %hash) {
   my @args = @$arrayRef; # dereference the array
   print qq{name $name with args "@args"\n};
}

また

while (my ($name, $arrayRef) = each %hash) {
   print "name\t$name\n";
   print "arg\t$_\n" foreach @$arrayRef;
}
于 2012-08-20T23:09:25.320 に答える
1

別のデータ構造が必要だと思います。これを試して:

use strict;
use warnings;
use Data::Dumper;

my @array;
my %hash;
my ( $name, $args, $key );

while ( my $line = <DATA> ) {
    chomp($line);
    if ( $line !~ /^\s/ ) {
        $key = $line;  #=~ /^\S+/g;
        print "Defined a name $key\n";
    }
    else {
        $line =~ s/^\s+//;
        push (@{$hash{$key}}, $line);
        print "Defined an arg $line\n";
    }
}

print Dumper(\%hash);

__DATA__
Sports
        Basketball
        Tennis
        Boxing
Guys
        Tom
        Dick
        Harry

出力:

$VAR1 = {
          'Sports' => [
                        'Basketball',
                        'Tennis',
                        'Boxing'
                      ],
          'Guys' => [
                      'Tom',
                      'Dick',
                      'Harry'
                    ]
        };

ソリューションを独自のコードに近づけようとしました。

Data::Dumper編集:配列/ハッシュに正確に何があるかを常にダンプするために使用されるマルチレベルのデータ構造を扱う場合。これは、このインスタンスなどの割り当ての問題を解決するのに役立ちます。

データ構造は次のようになります。

$VAR1 = [
          {
            'args' => [
                        'Basketball',
                        'Tennis',
                        'Boxing',
                        'Tom',
                        'Dick',
                        'Harry'
                      ],
            'name' => 'Guys'
          },
          $VAR1->[0],
          $VAR1->[0],
          $VAR1->[0],
          $VAR1->[0],
          $VAR1->[0],
          $VAR1->[0],
          $VAR1->[0]
        ];
于 2012-08-20T23:19:29.857 に答える