5

假设您需要创建某种“顶部”并具有如下代码:

$matches=array();
foreach ($array as $v){
   $matches[processing($v)]++;  
}

这将为索引需要创建的情况输出 a Notice: Undefined index

既然您知道必须创建索引,那么解决这些情况的最佳方法是什么?

我根据情况使用了这些解决方案:

  1. 抑制错误@$matches[$v]++;
    Pro : 很容易输入
    Con : 慢
  2. 检查它是否设置$matches[$v]=isset($matches[$v])?$matches[$v]++:1;
    Pro : 更快
    Con : 即使是速记形式也需要更长的时间来编写并且需要再使用 $matches[$v] 2 次

还有其他方法吗?
寻找最快的执行时间,因为我正在使用这个函数数千次或者一些更懒惰的输入方式,它仍然比 @ 更快

编辑:

在一个简单的情况下,你也$matches[$v]++;可以使用array_count_values() (正如 Yoshi 建议的那样)

4

3 回答 3

7

经过一些阅读、写作和测试,我得到了一些东西:

function inc(&$var){
    if (isset($var)) $var++;else $var=1;
}

并以为我找到了金子,但让我们先看看测试......

测试代码:

$a=array();

// Pre-Fill array code goes here
for($i=1;$i<100000;$i++) {
    $r=rand(1,30000);
    //increment code goes here
}

// Remove extra keys from array with:
//foreach ($a as $k=>$v) if ($v==0) unset($a[$k]);

执行时间:(仅供参考)

inc($a[$r])                             1.15-1.24
@$a[$r]++                                   1.03-1.09
$a[$r]=array_key_exists($r,$a)?$a[$r]++:1;  0.99-1.04

$a[$r]=!empty($a[$r])?$a[$r]++:1;               0.61-0.74
if (!empty($a[$r])) $a[$r]++;else $a[$r]=1; 0.59-0.67
$a[$r]=isset($a[$r])?$a[$r]++:1;                0.57-0.65
if (isset($a[$r])) $a[$r]++;else $a[$r]=1;  0.56-0.64


//with pre-fill
$a=array_fill(0,30000,0);                   +0.07(avg)
for($i=1;$i<=30000;$a[$i++]=0);             -0.04(avg)

//with pre-fill and unset
$a=array_fill(0,45000,0);                   +0.16(avg)
for($i=1;$i<=45000;$a[$i++]=0);             +0.02(avg)

结论:

  • @当然是最快的类型,我认为在这种情况下使用它没有任何问题,但也可以随意检查这个问题:Suppress error with @ operator in PHP
  • 完全抑制错误(在循环之前并在循环之后启用错误)通过ini_set()比所有性能都差
  • inc()看起来漂亮干净,易于键入并且会检查而不是抑制,但调用它看起来甚至比@
  • isset()比 略快empty(),但两者的表现相当
  • 有趣的是,使用速记 if语句稍慢
  • 预填充阵列时获得的最佳结果。即使长度未知,一个好的预测在巨大的数据集上仍然会稍微快一些
  • 奇怪的是,array_fill()需要的时间比for?!?!

RFC

我不认为这个答案是 100% 完整的,虽然,现在它看起来isset()是最快和@最懒惰的。
任何意见和想法表示赞赏!

于 2013-01-12T10:54:25.520 回答
1

您也许可以初始化匹配数组开始,使用array_combine将值组合$array为键并array_fill用初始 0 填充值

$matches = array_combine(array_values($array), array_fill(0, count($array), 0));
于 2013-01-10T15:29:40.113 回答
0

我经常做:

$matches=array();

foreach ($matches as $v){

    /* if $v is not empty, add 1, otherwise $v= 1 */
    $matches[$v]=(!(empty($matches[$v]))) ? $matches[$v]++ : 1;
}

你是对的。这有点罗嗦,但公平地说,它同时非常简洁。我使用empty()而不是isset()。不知道这在我脑海中是更快还是更慢。我认为它可能会更慢。

编辑

要回答您的编辑,我会这样做:

$matches=array();

foreach ($matches as $v){

    $x=function($v);

    /* if $v is not empty, add 1, otherwise $v= 1 */
    $matches[$x]=(!(empty($matches[$x]))) ? $matches[$x]++ : 1;
}

这样,您只需调用该函数一次。

于 2013-01-10T15:27:12.813 回答