5

今日、ブログ用のテキスト分析ツールに取り組んでいるときに、PHPの動作が非常に奇妙で、頭を抱えることができませんでした。テキストを正規化するときに、最小長未満の単語を削除しようとしたので、正規化方法で次のように記述しました。

if ($this->minimumLength > 1) {
    foreach ($string as &$word)
    {
        if (strlen($word) < $this->minimumLength) {
            unset($word);
        }
    }
}

不思議なことに、これは私の配列で許可された長さより下のいくつかの単語を残すでしょう。クラス全体で間違いを探した後、私はこれを試してみました。

if ($this->minimumLength > 1) {
        foreach ($string as $key => $word)
        {
            if (strlen($word) < $this->minimumLength) {
                unset($string[$key]);
            }
        }
    }

そして出来上がり!これは完璧に機能しました。さて、なぜこれが起こるのでしょうか?PHPのドキュメントを確認したところ、次のように記載されています。

PASSED BY REFERENCEである変数が関数内でunset()されている場合、ローカル変数のみが破棄されます。呼び出し元の環境の変数は、unset()が呼び出される前と同じ値を保持します。

独自のスコープがあるため、foreachここで機能しますか?calling environment

4

2 に答える 2

2

いいえ、ここには関数呼び出しはなく、変数は参照によって渡されていません(反復中に参照によってキャプチャしているだけです)。

参照によって反復する場合、反復変数は元の変数のエイリアスです。このエイリアスを使用して元の値を参照し、その値を変更すると、変更は繰り返される配列に表示されたままになります。

ただし、unsetエイリアスを作成すると、元の変数は「破棄」されません。エイリアスはシンボルテーブルから削除されるだけです。

foreach ($string as $key => &$word)
{
    // This does not mean that the word is removed from $string
    unset($word);

    // It simply means that you cannot refer to the iteration variable using
    // $word from this point on. If you have captured the key then you can
    // still refer to it with $string[$key]; otherwise, you have lost all handles
    // to it for the remainder of the loop body
}
于 2013-01-12T19:02:24.633 に答える
1

unset($word)ifステートメント内を呼び出すときは$word、配列に変更を加えることなく、変数自体を削除していました$string

于 2013-01-12T19:00:14.930 に答える