2013-07-25 85 views
15

有沒有辦法在匿名函數中停止array_walk從匿名函數break_ 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 ...)。

注:我不希望重寫代碼,我只是想知道IF這是可能的。

+3

你*可以*拋出,然後捕獲一個異常。當然,這是錯誤的方法,但這是可能的。 –

+0

不可能直接進行,但是您是在哪裏畫出了重寫代碼的行? ('Exception'解決方案聽起來像是可行的,但我會盡早使用一個普通的'foreach')。 – Jon

+0

@Jon:好的,我很好奇這樣的功能是否可行。我不想用'for' /'foreach',就是這樣(主要是理論上的問題:))。安東尼,你應該把它作爲答案。 –

回答

11

如上所述,理論上這是可能的,但我建議不要這樣做。以下是如何使用例外來突破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) 
*/ 
+0

如果這是您的應用程序的核心檢查,那麼您可能會拋出異常。做類似'拋出新的InvalidInputException;',然後正確處理它。但在大多數情況下,最好不要這樣做:)謝謝你的答案! –

6

你可以把一個靜態的標誌匿名函數內部:

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陣列中的所有值都是數字,他們將所有在場的過濾後。另一方面,數組中的任何非數字值都會影響已過濾數組中的內容(減少項目計數),並且比較結果會產生錯誤。