использовать array_map для проверки значений?
Вопрос
Можно ли использовать array_map() для проверки значений массива?Я хочу убедиться, что все элементы массива являются числовыми.
Я пробовал и то, и другое
$arrays = array(
array(0,1,2,3 )
, array ( 0,1, "a", 5 )
);
foreach ( $arrays as $arr ) {
if ( array_map("is_numeric", $arr) === FALSE ) {
echo "FALSE\n";
} else {
echo "TRUE\n";
}
}
и
$arrays = array(
array(0,1,2,3 )
, array ( 0,1, "a", 5 )
);
foreach ( $arrays as $arr ) {
if ( ( array_map("is_numeric", $arr) ) === FALSE ) {
echo "FALSE\n";
} else {
echo "TRUE\n";
}
}
И за то, и за другое я получаю
TRUE
TRUE
Можно ли это сделать?Если да, то что я делаю не так?
Примечание:Я знаю, что могу получить желаемую функциональность из цикла foreach.
Решение
array_map возвращает массив.Поэтому это всегда будет считаться «истинным».Теперь, если вы array_search
в случае ЛОЖЬ вы сможете получить желаемый эффект.
array_map() returns an array containing all the elements of
arr1 after applying the callback function to each one.
Это означает, что в настоящее время у вас есть массив, который содержит true или false для каждого элемента.Вам нужно будет использовать array_search(false,$array)
чтобы узнать, есть ли ложные значения.
Другие советы
Обычно я большой сторонник array_map()
, array_filter()
, и т. д., но в этом случае foreach()
будет лучшим выбором.Причина в том, что с array_map()
и другие, он пройдет через весь массив, несмотря ни на что.Но для ваших целей вам нужно пройтись по массиву только до тех пор, пока не встретите значение, для которого is_numeric()
возвращает false, и, насколько мне известно, в PHP нет способа выйти из этих методов.
Другими словами, если в вашем массиве 1000 элементов, а пятый не является числовым, используйте array_map()
все равно проверит оставшиеся 995 значений, даже если вы уже знаете, что массив не прошел ваш тест.Но если вместо этого вы используете foreach() и имеете его break
на is_numeric() == false
, то вам нужно будет проверить только первые пять элементов.
Вы могли бы использовать filter, но в итоге получается ужасный фрагмент кода
$isAllNumeric = count(array_filter($arr, "is_numeric")) === count($arr)
Использование пользовательской функции делает его немного лучше, но все еще не идеальным
$isAllNumeric = count(array_filter($arr, function($x){return !is_numeric($x);})) === 0
Но если бы вы использовали пользовательские функции, array_reduce работал бы, но у него все еще есть некоторые недостатки.
$isAllNumeric = array_reduce($arr,
function($x, $y){ return $x && is_numeric($y); },
true);
Недостатки заключаются в том, что он не сломается, когда найдет то, что ему нужно, поэтому приведенные выше функциональные предложения не очень эффективны.Вам нужно было бы написать функцию, подобную этой:
function array_find(array $array, $callback){
foreach ($array as $x){ //using iteration as PHP fails at recursion
if ( call_user_func($callback, array($x)) ){
return $x;
}
}
return false;
}
И используйте это вот так
$isAllNumeric = array_find($arr, function($x){return !is_numeric($x);})) !== false;
у меня есть две крошечные, но чрезвычайно полезные функции в моей «стандартной библиотеке»
function any($ary, $func) {
foreach($ary as $val)
if(call_user_func($func, $val)) return true;
return false;
}
function all($ary, $func) {
foreach($ary as $val)
if(!call_user_func($func, $val)) return false;
return true;
}
в твоем примере
foreach ( $arrays as $arr )
echo all($arr, 'is_numeric') ? "ok" : "not ok";
ИМХО, более элегантный подход.:
foreach ($arrays as $array)
{
if (array_product(array_map('is_numeric', $array)) == true)
{
echo "TRUE\n";
}
else
{
echo "FALSE\n";
}
}
Это вернет true, если все значения являются числовыми, и false, если какое-либо из значений не является числовым.