19

有没有办法array_walk从匿名函数内部停止?

这是一些示例代码(有效)来说明我的意思,它检查数组是否只有数值。

$valid = true;
array_walk($parent, function ($value) use (&$valid) {
    if (!is_numeric($value)) {
        $valid = false;
    }
});

return $valid ? 'Valid' : 'Invalid';

如果我有一个足够大的数组,并且第一个条目无效,那么其余的(冗余)检查仍然完成,所以我想停止执行。

使用break/continue不起作用(错误:)Fatal error: Cannot break/continue 1 level in ...

注意:我不想重写代码,我只想知道是否可能。

4

2 回答 2

16

如前所述,理论上这是可能的,但我建议不要这样做。以下是如何使用异常来突破array_walk.

<?php
$isValid = false;

$array = range(1, 5);

try {
    array_walk($array, function($value) {
        $isAMagicNumber = 3 === $value;
        if ($isAMagicNumber) {
            throw new Exception;
        } 
    });
}catch(Exception $exception) {
    $isValid = true;
}

var_dump($isValid);

/*
    bool(true)
*/
于 2013-07-25T08:55:39.270 回答
9

您可以在匿名函数中放置一个静态标志:

array_walk($ary, function($item) {
    static $done = false;
    if($done) {
        return;
    }

    // … your code

    if($myBreakCondition) {
        $done = true;
        return;
    }
});

这实际上并没有停止迭代,但设置标志后的所有进一步循环都什么都不做。效率不是很高,但如果迭代的数组不是太大,它可能不会对性能产生任何更大的影响。

在您的情况下,代码将是:

$valid = true;
array_walk($parent, function($value) use(&$valid) {
    static $done = false;
    if($done) {
        return;
    }

    if(!is_numeric($value)) {
        $valid = false;
        $done = true;
        return;
    }
});
return $valid ? 'Valid' : 'Invalid';

但实际上,如果根本没有“中断”,那并没有太大的区别。只会为每个无效值分配“假”,这无关紧要,因为结果仍然是假的。也许我的静态变量作弊会更有效率。

就您个人而言,我会array_filter改用:

$valid = count(array_filter($parent, 'is_numeric')) == count($parent);

要不就

$valid = array_filter($parent, 'is_numeric')) == $parent;

如果$parent数组中的所有值都是数字,则它们将在过滤后全部存在。另一方面,数组中的任何非数字值都会影响过滤数组中的内容(减少项目计数),并且比较会产生错误。

于 2015-04-28T04:52:12.557 回答