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 参数,它将作为第三个参数传递给回调函数名。

这是第三个参数。它不是一个引用,它只是一个传递给你的回调函数的值。


您的问题的一个(众多)解决方案是使用对象(对象总是通过引用传递):

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

虽然发送给回调函数的第三个参数本身不能是引用,但它可以包含引用。

另一种方法(使用对象或将回调包装在闭包中)是将数组传递给回调,其中包含对要更新的变量的引用。包装数组按值传递,但它包含的只是您要更改的引用值。

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 回答