通过引用array_walk()传递数组后的空数组

时间:2013-06-14 18:34:40

标签: php arrays reference traversal

我做了这个小班:

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()的输出外,所有输出实际上都是正确的。似乎变量$sortedPhrasesarray_walk()之后以某种方式被清除。

3 个答案:

答案 0 :(得分:5)

更好地了解array_walk's documentation page

  

<强>用户数据

     

如果提供了可选的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);
});

答案 1 :(得分: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];
        // …
    }
}

答案 2 :(得分:1)

很确定这是错误的:

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

所以,试试这个:

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

并在$sortedPhrases中返回您的值,不要使用按引用传递(个人事物)