1

私はこの小さなクラスを作りました:

class Analyzer {
    public static function analyze($phrases) {
        $sortedPhrases = array();
        array_walk($phrases, array('self', 'splitByLength'), $sortedPhrases);
        var_dump($sortedPhrases);
    }

    private static function splitByLength($item, $key, &$resArr) {
        // line stolen from here: http://stackoverflow.com/a/4786840/603003
        // thanks to arnaud576875 <http://stackoverflow.com/users/576875/arnaud576875>
        $len = count( preg_split('#\PL+#u', $item, -1, PREG_SPLIT_NO_EMPTY) );
        if (!isset($resArr[$len])) {
            $resArr[$len] = array();
        }
        $resArr[$len][] = $item;

        var_dump($resArr);
    }
}

$phrases = array(
    "I can't believe the great content",
    "I can't understand the superior information",
    "I can't comprehend the amazing data",
    "I cannot analyze the amazing data",
    "I haven't written to the amazing data"
);
Analyzer::analyze($phrases);

スクリプトを実行すると、次の出力が得られます。

array (size=1)
  7 => 
    array (size=1)
      0 => string 'I can't believe the great content' (length=33)

...

array (size=3)
  7 => 
    array (size=3)
      0 => string 'I can't believe the great content' (length=33)
      1 => string 'I can't understand the superior information' (length=43)
      2 => string 'I can't comprehend the amazing data' (length=35)
  6 => 
    array (size=1)
      0 => string 'I cannot analyze the amazing data' (length=33)
  8 => 
    array (size=1)
      0 => string 'I haven't written to the amazing data' (length=37)

array (size=0)
  empty

Analyzer::analyze()からの最後の出力を除いて、すべての出力は実際には正しいです。array_walk()の後に変数$sortedPhrasesが何らかの形でクリアされているようです。

4

3 に答える 3

5

array_walkのドキュメンテーション ページをよく見てください。

ユーザーデータ

オプションの userdata パラメータが指定されている場合は、3 番目のパラメータとしてコールバック funcname に渡されます。

それが 3 番目のパラメーターです。これは参照ではなく、コールバック関数に渡される単なる値です。


あなたの問題に対する(多くの)解決策の1つは、代わりにオブジェクトを使用することです(オブジェクトは常に参照によって渡されます):

class Analyzer {
    public static function analyze($phrases) {
        $arrObj = new ArrayObject();
        array_walk($phrases, array('self', 'splitByLength'), $arrObj);
        var_dump($arrObj->getArrayCopy());
    }

    private static function splitByLength($item, $key, $arrObj) {
        // line stolen from here: http://stackoverflow.com/a/4786840/603003
        // thanks to arnaud576875 <http://stackoverflow.com/users/576875/arnaud576875>
        $len = count( preg_split('#\PL+#u', $item, -1, PREG_SPLIT_NO_EMPTY) );
        if (!isset($arrObj[$len])) {
            $arrObj[$len] = array();
        }
        $arrObj[$len][] = $item;

        var_dump($arrObj->getArrayCopy());
    }
}

( である必要はありませんArrayObject。配列プロパティを持つ stdClass オブジェクトにすることも、必要に応じて独自のクラスを作成することもできます...)


または、本当に参照を操作したい場合は、匿名関数内で呼び出しをラップできます。

$static = get_called_class();
array_walk($phrases, function($item, $key) use($static, &$sortedPhrases){
  $static::splitByLength($item, $key, $sortedPhrases);
});
于 2013-06-16T20:37:48.907 に答える
2

コールバック関数に送信される 3 番目の引数自体を参照にすることはできませんが、参照を含めることはできます。

別のアプローチ (オブジェクトを使用するか、コールバックをクロージャーでラップする) は、更新する変数への参照を含む配列をコールバックに渡すことです。ラッピング配列は値で渡されますが、含まれているのは変更したい参照値だけです。

class Analyzer {
    public static function analyze($phrases) {
        // …
        array_walk($phrases,
                   array('self', 'splitByLength'),
                   array(&$sortedPhrases));
        // …
    }

    private static function splitByLength($item, $key, $extra_args) {
        $resArr = &$extra_args[0];
        // …
    }
}
于 2013-06-18T21:38:32.917 に答える
1

これは間違っていると確信しています:

array_walk($phrases, array('self', 'splitByLength'), $sortedPhrases);

だから、これを試してください:

$sortedPhrases = array_walk($phrases, 'splitByLength');

で値を返し、$sortedPhrases参照渡しを使用しないでください(個人的なこと)

于 2013-06-14T18:41:23.990 に答える