2

名前を表す文字列で埋められた 2 つの配列 と@namesがあります。は 2 次元であり、無名配列への参照を保持していますが、重要なデータの場所はです。ループして、 にない名前を見つけたい。@employees@names@names[i][0]@names@employees

最初は、逆方向にループして@names比較し@employees、一致するものを削除する@namesとうまくいくと思っていましたが、いくつかのエラーが発生しました。ここに私が持っているものがあります:

for my $i (reverse(0 .. $#names)) {
  foreach my $employee (@employees) {
    if ($names[$i][0] eq $employee) {  # line 67
      splice(@names, $i, 1);
    }
  }
}

このエラーが発生します:

script.pl の 67 行目、2 行目の文字列 eq で初期化されていない値が使用されています。

文字列はすべて配列で定義されています。したがって、これはループ中に配列内の要素を削除したことが原因であると推測していますが、配列を逆方向にループすると、このような問題が発生するのを防ぐことができると思いました。

では、ループのどこで間違っているのでしょうか? また、私はこのループに本当に苦労しており、私の思考プロセス全体に何か問題があることを示唆しています. これを行うためのより良い方法はありますか?

4

2 に答える 2

10

ここで明示的にループする理由はありません。名前をフィルタリングしたい:それはgrep. メンバーシップを確認したい場合: これも a で実行できgrepます。

@names = grep {my $name = $$_[0]; not grep $_ eq $name, @employees} @names;

内部配列の繰り返しスキャンは特に効率的ではありません。事前にセット (実際にはハッシュ) を事前設定することで回避できます。

my %employees = map +($_ => 1), @employees;
@names = grep !$employees{$$_[0]}, @names;
于 2012-06-13T19:26:53.490 に答える
0

コードを提供しないと、@names の新しいリストを返すことになります。@names の各名前について、@employees に含まれているかどうかを確認し、そうでない場合は名前の新しいリストに追加します。

于 2012-06-13T19:13:43.950 に答える