5

ある種の「トップ」を作成し、次のようなコードを作成する必要があるとします。

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

Notice: Undefined indexこれにより、インデックスの作成が必要な場合のが出力されます。

インデックスを作成する必要があることを知っているので、これらのケースに取り組むための最良の方法は何でしょうか?

ケースに応じて、これらのソリューションを使用しました。

  1. エラーの抑制@$matches[$v]++;
    Pro:入力が非常に簡単
    Con:遅い
  2. 設定されているかどうかの確認$matches[$v]=isset($matches[$v])?$matches[$v]++:1;
    Pro:fast
    Con:省略形でも書き込みに時間がかかり、$ matches[$v]をさらに2回使用する必要があります

他に方法はありますか?この関数を何千回も使用しているので、最速の実行時間
を探しています。または、@よりもまだ高速な入力の怠惰な方法を探しています。

編集:

あなたが持っている単純なケースでは、あなた$matches[$v]++;も使うことができますarray_count_values() (ヨッシーが提案したように)

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)

結論:

  • @もちろん、入力するのが最速であり、この場合に使用しても問題はありませんが、この質問もお気軽に確認してください: PHP で @ 演算子を使用してエラーを抑制します。
  • エラーを完全に抑制 (ループの前とループの後にエラーを有効にする)ini_set()は、すべてのパフォーマンスよりも悪い
  • inc()見栄えがよく、きれいで、入力が簡単で、抑制ではなくチェックを行いますが、それを呼び出すと、@
  • isset()は よりわずかに高速ですempty()が、どちらもほぼ同じ性能を発揮します
  • 興味深いことに、短縮 ifステートメントを使用すると少し遅くなります
  • 配列を事前に入力すると、最良の結果が得られます。長さが不明な場合でも、巨大なデータセットでは適切な予測がわずかに高速になります
  • 奇妙なことに、?!?!array_fill()よりも少し時間がかかります。for

RFC

この回答が 100% 完了したとは考えていませんが、現時点でisset()は最速で最も@怠惰なようです。
コメントやアイデアは大歓迎です!

于 2013-01-12T10:54:25.520 に答える
1

からの値をキーとしてarray_combine結合し、値を最初の 0 で埋めるために使用して、最初にマッチ配列を初期化することができます。$arrayarray_fill

$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;
}

そうすれば、関数を 1 回だけ呼び出すことができます。

于 2013-01-10T15:27:12.813 に答える