2011-11-29 36 views
3

我在寫一個名爲all的函數來檢查數組$arr中的所有元素,返回一個值boolean(基於$f的返回值)。這是工作正常傳遞自定義函數(請參閱代碼$gte0已傳遞到all)。PHP是否有一個true()函數?

但是有時候一個只想檢查數組包含了所有true值:all(true, $arr)將無法​​正常工作becase的true作爲boolean傳遞(和true不是函數名)。 PHP有一個本地true()類似的功能?

function all($f, array $arr) 
{ 
    return empty($arr) ? false : array_reduce($arr, function($v1, $v2) use ($f) { 
     return $f($v1) && $f($v2); 
    }, true); 
} 

$test = array(1, 6, 2); 
$gte0 = function($v) { return $v >= 0; } 

var_dump(all($gte0, $test)); // True 

$test = array(true, true, false); 
$id = function($v) { return $v; } // <-- this is what i would avoid 
var_dump(all($id, $test)); // False 

all(true, $test); // NOT WORKING because true is passed as boolean 
all('true', $test); // NOT WORKING because true is not a function 

編輯:另一種方式可以在all功能檢查$f

$f = is_bool($f) ? ($f ? function($v) { return $v; } 
    : function($v) { return !$v; }): $f; 

添加此,呼籲alltrue是完全沒有問題後。

+3

這是編寫代碼IMO的一種非常具有誤導性的方式。特別是你的第二段代碼,很難理解正確的流程 – dynamic

+0

@ yes123你應該在你的評論結尾添加恕我直言。 – gremo

+1

@格雷莫:評論總是陳述性的,絕不會分享意見。這就是爲什麼他們被稱爲評論;) – hakre

回答

3

intval可能做你要找的內容(尤其是在陣列只包含在你的榜樣整數):

var_dump(all('intval', $test)); // False 

然而,many types to integer conversions are undefined in PHP和隨着浮動這將圓到零,所以這可能不是你想要的。

更正確的「功能」是布爾的真實相反:empty,但它不是一個功能,所以你不能用它(和反轉返回值):

var_dump(!all('empty', $test)); // Does not work! 

還有在PHP中不是函數boolval或類似函數,所以如果你需要它可以自己編寫;)

另外你的all函數可以被優化。在迭代時,如果當前結果已經爲FALSE,則最終結果將始終爲FALSE。沒必要反正叫$f()n * 2時間:

function all($f, array $arr) 
{ 
    $result = (bool) $arr; 
    foreach($arr as $v) if (!$f($v)) return FALSE; 
    return $result; 
} 

編輯:knittl is right指向array_filter,其轉換沒有給定函數,這似乎冷靜,因爲沒有「boolval」功能爲布爾:

function all($f, array $arr) 
{ 
    return ($c = count($arr)) 
     && ($f ? $arr = array_map($f, $arr) : 1) 
     && $c === count(array_filter($arr)); 
} 

var_dump(all(0, $test)); // False 

使第一個函數參數成爲可選將會爲您在每個數組元素上進行正確的布爾轉換,這要歸功於array_filter

+0

謝謝,這是迄今爲止最相關的答案。我會優化它。 – gremo

+0

@Gremo:我編輯它,並用'array_filter'添加了一個'all'函數變體,這也是knittl的一個很好的指針。 – hakre

+1

+1爲早期循環!我認爲這是關於運行時和內存的最佳代碼(甚至可以節拍array_filter)。我也有類似的想法。順便說一句,你應該可以做'$ result =(bool)$ a; foreach($ a as $ v){if(!$ f($ v))返回false; } return $ result;',不需要和所有結果 – knittl

1

PHP中沒有任何true()函數,您應該將該值與true進行比較。

嘗試

return ($f === $v1) && ($f === $v2); 

,而不是

return $f($v1) && $f($v2); 
+0

是的,但它不會與'$ gte0',例如。 – gremo

+0

第一句話感到困惑 - 應該在PHP之後有一段時間嗎? –

0

我認爲這應該工作:

function all($f, array $arr) 
{ 
    return empty($arr) ? false : array_reduce($arr, function($v1, $v2) use ($f) { 
     return $f($v1) && $f($v2); 
    }, true); 
} 

function isTrue($a) 
{ 
    return true === $a; 
} 

all("isTrue", $test); 
+0

和我一樣:'$ id = function($ v){return $ v; }'(身份函數)... – gremo

+0

...或'function isTrue($ a){return(bool)$ a; }',根據需要 – DaveRandom

+0

@Gremo我認爲傳入'all()'的參數的引用是相關的。 '「isTrue」'是我的例子中的一個字符串,而'true'是你的一個布爾值。 –

2

你可以使用PHP的array_filter功能,它會刪除所有 'falsy' 值從如果沒有指定回調,則爲數組:

$a = array (true, true, false); 
var_dump($a == array_filter($a)); 
+0

不相關。請再看代碼... – gremo

3

更好地傳遞一個函數來將值映射到布爾值,然後可以減少到最終值。

function all($map, $data) { 
    if (empty($data)) { return false; } 
    $reduce = function($f, $n) { 
    return $f && $n; 
    }; 
    return array_reduce(array_map($map, $data), $reduce, true); 
} 

$gte0 = function($v) { return $v >= 0; }; 
$gte2 = function($v) { return $v >= 2; }; 

$data = array(1, 2, 3, 4, 5); 
var_dump(all($gte0, $data)); 
var_dump(all($gte2, $data)); 

然後功能的結果仍然是預期的,但測試可以根據需要插入。你可以走得更遠了一步,同時允許在地圖和減少功能傳遞

function mr($map, $reduce, $data) { 
    return array_reduce(array_map($map, $data), $reduce, true); 
} 
相關問題