Php 如果多维数组列的所有值都是数值,则返回最快值为TRUE

Php 如果多维数组列的所有值都是数值,则返回最快值为TRUE,php,arrays,multidimensional-array,null,numbers,Php,Arrays,Multidimensional Array,Null,Numbers,是否有更快的方法来检查一个表中是否存在数字(而不是null) php中多维数组的列(例如,number9) 尝试: 下面的if语句似乎工作正常 $arr=Array( [0] => Array ( [date] => 2019-01-16 [number1] => 20.4 [number2] => 20.54 [number3] => 19.71

是否有更快的方法来检查一个表中是否存在数字(而不是
null
) php中多维数组的列(例如,
number9

尝试: 下面的
if语句
似乎工作正常

$arr=Array(
    [0] => Array
        (
            [date] => 2019-01-16
            [number1] => 20.4
            [number2] => 20.54
            [number3] => 19.71
            [number4] => 19.73
            [number5] => 70849266
            [number6] => 70849266
            [number7] => -0.65
            [number8] => -3.189
            [number9] => 20.0902
            [string1] => Jan 16
            [number10] => 0.047796070100903
        )

    .
    .
    .

    [21] => Array
        (
            [date] => 2019-01-17
            [number1 => 19.49
            [number2] => 20.51
            [number3] => 19.02
            [number4] => 20.25
            [number5] => 85018421
            [number6] => 85018421
            [number7] => 0.52
            [number8] => 2.636
            [number9] => 19.7988
            [string1] => Jan 17
            [number10] => 0.075411577270313
        )

);


function isNumeric($var){
  if (is_numeric($var)){
    return true;
  } else {
    return false;
  }
}


if((array_walk(array_column($arr, "number8"), 'isNumeric'))!=1)

array\u walk
只是将函数应用于每个元素,它不会告诉您是否成功
array\u filter
将执行您要查找的操作,因为它将删除与filter函数不匹配的任何元素

$result = array_filter(array_column($arr, "number8"), 'is_numeric');
if (count($result) === count($arr)) {
    // all numeric
} else {
    // one or more not numeric
}

注意:您可以在这里直接使用
is\u numeric
,因为回调只接受一个参数,即数组元素的值。

使用
foreach
循环:

$bool = true;
foreach ($arr as $row)
{
    if (!is_numeric($row['number8']))
    {
        $bool = false;
        break;
    }
}

正如我在评论中所说:

下面的if语句似乎工作正常

然而,考虑到你提出的代码,我怀疑:让我们看看它

function isNumeric($var){ ... }

if(array_walk(array_column($arr, "number8"), 'isNumberic'))!=1
第一件也是最明显的事情是这两件事

  • isNumeric
    vs
    isNumeric
    ,这是一个致命的未定义函数错误(拼写/打字错误)
  • )=1
    那么这超出了实际情况,或者换一种说法,如果(…){!=1}
让我们假设这些只是问题中的拼写错误。即使您的代码没有我上面提到的2个“缺陷”,您仍然会遇到这个问题,
array\u walk
通过引用工作并简单地返回true(总是)。Pass by reference更新“原始”变量,而不返回其副本(在array_walk的情况下)

返回值 返回TRUE

当然,这只会让你的病情无论如何都得以缓解。因此,您应该始终测试条件的通过和失败(正如我在其中放置一些“固定”的坏数据所做的那样)。通过这种方式,我100%确切地知道我的代码的行为

其他人已经发布了如何纠正这一点,但不是你做错了什么。但为了完整起见,我还是会发布一个答案

$arr = array (
    0 => 
    array (
        'date' => '2019-01-16',
        'number1' => 20.4, 
        'number2' => 20.54,
        'number3' => 19.71,
        'number4' => 19.73,
        'number5' => 70849266,
        'number6' => 70849266,
        'number7' => -0.65,
        'number8' => -3.189,
        'number9' => 20.0902,
        'string1' => 'Jan16',
        'number10' => 0.047796070100903
    ),
    array (
        'date' => '2019-01-16',
        'number1' => 20.4, 
        'number2' => 20.54,
        'number3' => 19.71,
        'number4' => 19.73,
        'number5' => 70849266,
        'number6' => 70849266,
        'number7' => -0.65,
        'number8' => 'foo',#intentially not number
        'number9' => 20.0902,
        'string1' => 'Jan16',
        'number10' => 0.047796070100903
    ),

);

$col = array_column($arr, "number8");
$col1 = array_filter($col, 'is_numeric');

if($col != $col1){
    echo "not the same\n";
}
输出:

not the same

我应该提到的是,没有“需要”计算这些值,因为PHP可以比较复杂对象的相等性。当我们在(可能)删除某些元素后将相同的“根”数组(
$col
在本例中)与其自身进行比较时,如果没有删除任何元素,那么两个数组不仅应该具有相同的长度,而且应该“相同”

此外,如果要在一行(条件内)中执行此操作,可以执行以下操作:

if( ($col = array_column($arr, "number8")) && $col != array_filter($col, 'is_numeric')){
    echo "not the same\n";
}
阅读起来有点困难,请注意
$col=array\u column
赋值。

以下是我的想法。
首先,只需过滤数组中的纯数值,并与原始值进行比较:

function with_array_filter($arr) {
    return $arr == array_filter($arr, 'is_numeric');
}
第二个示例使用了先转换为浮点,然后再转换为字符串的方法,请记住,这对于非常大的数字来说并不准确,但是似乎是最快的(如果您关心这个问题的话):

然而,最简单的解决方案可能是只
foreach
函数中的数组,然后提前返回:

function is_numeric_array_with_func($arr) {
    foreach ($arr as $b) {
        if (!is_numeric($b)) {
            return false;
        }
    }
    return true;
}
在PHP7.2上通过100000次迭代测试了20个元素的数组:

$falseArray = [
    '1',
    2.5,
    -10,
    32,
    11.0,
    2.5,
    100101221,
    345,
    -10,
    '-10',
    '+10',
    '10',
    12,
    PHP_INT_MAX,
    PHP_INT_MAX + 1.4e5,
    '-10',
    null,
    'a',
    '5',
    5
];

Matt Fryer
Time: 4.8473789691925

is_numeric_array_with_func
Time:  4.0416791439056

is_numeric_array_with_cast
Time:  3.2953300476074

with_array_filter
Time:  3.99729180336

非常感谢所有人,感谢你们伟大的回答

在我的电脑上,我在PHP 5.5.38中尝试了四个函数,迭代次数约为5000次,总次数如下:

"is_numeric_array_with_cast total time is 0.44153618812561"
"with_array_filter total time is 0.21628260612488"
"is_numeric_array_with_func total time is 0.14269280433655"
"is_numeric_matt_fryer total time is 0.155033826828"


$t1=$t2=$t3=$t4=0;
foreach($arrs as $k=>$arr){
    $s1=microtime(true);
    is_numeric_array_with_cast(array_column($arr, "number8"));
    $e1=microtime(true)-$s1;
    $t1=$t1+$e1;

    $s2=microtime(true);
    with_array_filter(array_column($arr, "number8"));
    $e2=microtime(true)-$s2;
    $t2=$t2+$e2;


    $s3=microtime(true);
    is_numeric_array_with_func(array_column($arr, "number8"));
    $e3=microtime(true)-$s3;
    $t3=$t3+$e3;

    $s4=microtime(true);
    is_numeric_matt_fryer(array_column($arr, "number8"),"number8");
    $e4=microtime(true)-$s4;
    $t4=$t4+$e4;

}






function is_numeric_array_with_cast($arr) {
    foreach ($arr as $b) {
        if ($b != (string)(float)$b) {
            return false;
        }
    }
    return true;
}


function with_array_filter($arr) {
    return $arr == array_filter($arr, 'is_numeric');
}


function is_numeric_array_with_func($arr) {
    foreach ($arr as $b) {
        if (!is_numeric($b)) {
            return false;
        }
    }
    return true;
}

function is_numeric_matt_fryer($arr,$str){
  $bool = true;
  foreach ($arr as $row)
  {
      if (!is_numeric($row[$str]))
      {
          $bool = false;
      }
  }
  return $bool;
}

为什么不直接在
array\u walk
中使用
is\u numeric
?在大多数情况下,使用foreach迭代数组会比array\u walk执行得更快。@Dharman
array\u walk()
中的回调需要使用两个参数。
下面的if语句似乎工作正常
鉴于您提出的代码,我怀疑,但是,如果拼写相同,则可能实际发生了一些事情
isNumeric
vs
isNumeric
。当然,您仍然会遇到这个问题=1不确定该怎么做,但不正确。您可能认为它是有效的,但数组walk总是返回TRUE。(根据文档)如果可能,请在此处发布您的结果,这会很有趣:)
如果(!$bool=$bool&&is_numeric($row['number8'))中断
可能更有效…除非处理非常大的数组(如上万个元素),否则不同数组迭代方法之间的性能不太可能有显著差异。
$arr
的计数与
$result
的计数不同,一个是计算整个数组,一个是数列。此外,在这种情况下,
计数实际上不需要。:)也就是说它确实有效,只是因为使用了数组中所有项中存在的单个列,但它似乎是未来令人头痛的潜在原因。
"is_numeric_array_with_cast total time is 0.44153618812561"
"with_array_filter total time is 0.21628260612488"
"is_numeric_array_with_func total time is 0.14269280433655"
"is_numeric_matt_fryer total time is 0.155033826828"


$t1=$t2=$t3=$t4=0;
foreach($arrs as $k=>$arr){
    $s1=microtime(true);
    is_numeric_array_with_cast(array_column($arr, "number8"));
    $e1=microtime(true)-$s1;
    $t1=$t1+$e1;

    $s2=microtime(true);
    with_array_filter(array_column($arr, "number8"));
    $e2=microtime(true)-$s2;
    $t2=$t2+$e2;


    $s3=microtime(true);
    is_numeric_array_with_func(array_column($arr, "number8"));
    $e3=microtime(true)-$s3;
    $t3=$t3+$e3;

    $s4=microtime(true);
    is_numeric_matt_fryer(array_column($arr, "number8"),"number8");
    $e4=microtime(true)-$s4;
    $t4=$t4+$e4;

}






function is_numeric_array_with_cast($arr) {
    foreach ($arr as $b) {
        if ($b != (string)(float)$b) {
            return false;
        }
    }
    return true;
}


function with_array_filter($arr) {
    return $arr == array_filter($arr, 'is_numeric');
}


function is_numeric_array_with_func($arr) {
    foreach ($arr as $b) {
        if (!is_numeric($b)) {
            return false;
        }
    }
    return true;
}

function is_numeric_matt_fryer($arr,$str){
  $bool = true;
  foreach ($arr as $row)
  {
      if (!is_numeric($row[$str]))
      {
          $bool = false;
      }
  }
  return $bool;
}