1

配列のハッシュと通常の配列がありますが、状況 (つまり、プログラムの実行時にユーザーが選択するオプション) に応じて、これらのうちの 1 つだけが定義されます。

問題を示すコード例:

my %hashofarrays;
my @array;

#...
#Some code between here where either %hashofarrays or @array gets defined
#...

if (defined @array) {

    foreach my $var1 (@array) {
        print "var1 is: $var1\n";
        call_subroutine($var1);
        print "Something else is printed";
        call_anothersubroutine($var1);
        call_differentsubroutine($var1);
    }

} 

if (defined %hashofarrays) {

    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        foreach my $var1 (@{$hashofarrays{$key}}) {
            call_subroutine($var1);
            print "Something else is printed";
            call_anothersubroutine($var1);
            call_differentsubroutine($var1);
        }
    }
}
   

上記のコードでわかるように、が定義されている@arrayか定義されているかによって%hashofarrays、対応するifステートメントが実行されます。

問題:

ただし、これに関する問題は、次のコード行が両方のifステートメントで重複していることです。

    call_subroutine($var1);
    print "Something else is printed";
    call_anothersubroutine($var1);
    call_differentsubroutine($var1);

明らかに、これらのforeachループに大量のコードが含まれている場合、膨大な量のコードが複製されることになります。

foreachループに関して、このコードの重複を回避できる方法はありますか/最善の方法は何ですか?

実際には、次のようなことを行う方法はありますか: (このコードが機能しないことは十分承知していますが、達成しようとしていることを説明しています)

if (defined @array) {
    foreach my $var1 (@array) {
} elsif (defined %hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        foreach my $var1 (@{$hashofarrays{$key}}) {

} #ending bracket of if statement

        call_subroutine($var1);
        print "Something else is printed";
        call_anothersubroutine($var1);
        call_differentsubroutine($var1); 

}  #ending bracket of whatever foreach loop is used

ここで明らかなことを見落としているかもしれませんが、これを行う論理的な方法がわかりませんか?

4

3 に答える 3

5

まず第一に、defined @arrayそして間違っていdefined %hashofarraysます。それらは常に定義されています。要素が含まれているかどうかをテストします。あなたも警告を受けているはずです!if (@array)if (keys %hashofarrays)defined(@array) is deprecated

必要なのは別のサブルーチンです。

sub loop_body {  # just use some better name!
  my ($var) = @_;
  call_subroutine($var);
  print "Something else is printed";
  call_anothersubroutine($var);
  call_differentsubroutine($var);
}

それで:

if (@array) {
    foreach my $var1 (@array) {
        print "var1 is: $var1\n";
        loop_body($var1);
    }
} elsif (keys %hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        foreach my $var1 (@{$hashofarrays{$key}}) {
            loop_body($var1)
        }
    }
}

コールバックを使用して、ソリューションをより柔軟にすることもできます。

 sub loop_with_cb {
   my $cb = shift;
   for my $var (@_) {
     if ($cb) {
       local $_ = $var; # make $_ visible to the callback
       $cb->($var);
     }
     call_subroutine($var);
     print "Something else is printed";
     call_anothersubroutine($var);
     call_differentsubroutine($var);
   }
 }

それで:

if (@array) {
    loop_with_cb(
      sub { print "var1 is: $_\n" },
      @array,
    );
} elsif (keys %hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        loop_with_cb(undef, @{ $hashofarrays{$key} });
    }
}
于 2013-09-03T12:10:37.270 に答える
1

別の関数を使用すると役立つ場合がありますが、

if (@array) {
    my_func(\@array);
} 
if (%hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        my_func($hashofarrays{$key});
    }
}

sub my_func {
    my ($arr) = @_;

    foreach my $var1 (@$arr) {
        call_subroutine($var1);
        print "Something else is printed";
        call_anothersubroutine($var1);
        call_differentsubroutine($var1);
    }

}
于 2013-09-03T12:13:36.617 に答える
0

アモンが言ったように、if (defined @array)それは間違っていif (@array)ますが、あなたがelse. に直接進むことができ、が空のfor (@array)場合@arrayは、基本的にループをスキップしてゼロ回反復しますif

@arrayそれが邪魔にならないので、 のすべての要素と のすべてのキーに対して同じことをしたいようです%hash of arraysね。そのためにはさえ必要ありませんsub

for (@array, map { @$_ } values %hashofarrays) {
  my $var1 = $_;
  print "var is: $var1\n";
  call_subroutine($var1);
  print "Something else is printed";
  call_anothersubroutine($var1);
  call_differentsubroutine($var1);
}

編集:%hashofarraysキーではなく、配列の内容をループするようにコードを修正しました。$var1ハッシュキーを出力する代わりにホアをループするときに出力されるため、これはまだ最初の質問のコードと完全に一致していませんが、OPの実際のユースケースではハッシュへのインデックス作成以外のキー。その場合、とにかく実際には必要ありません (values %hoa代わりに使用できるため)。

于 2013-09-03T12:50:25.933 に答える