1

別の値に基づいて、PHP配列の最高のキーを見つけようとしています。

$values = array(0,0,50,100,200,400,800);

値が125の場合、3が返されます。400から799の値の場合、5が返されます。

$output = -1;
$input = 436;
$length = count($values);
for($i=1;$i<=$length;$i++){
    if($values[$i]<=$input) { $output++; }
}
// Returns 5

配列をループすることはできますが、100個の値があり、ユーザーごとのページ読み込みごとに最大20回使用されるため、ページの速度が大幅に低下する可能性があります。欠けている特別な機能はありますか?または、アレイをforeachする必要がありますか?

配列は常に順序付けられており、変更されることはありません。

4

2 に答える 2

1

申し訳ありませんが、AFAIKでは本当にこのトラフをループする必要があります。

配列が順序付けられている場合は、より高い最初のインデックスを見つけて、残りを追加するだけです。


編集:これが私がベンチマークに使用したコードです:

set_time_limit(0);

$a = array(0,0,50,100,200,400,800);
$a = array_merge(range(0, 100000), $a);

sort(a); // we need this since array_merge will not maintain the sequence

$result = array
(
    'testWithForeach' => 0,
    'testWithArrayFlip' => 0,
    'testWithArraySearch' => 0,
);

foreach (range(0, 1000, 10) as $n) // search values $n to try
{
    for ($i = 0; $i < 10; ++$i) // how many times to run each test
    {
        foreach (array_keys($result) as $test) // divide the CPU usage fairly (inner-most loop)
        {
            $start = microtime(true); call_user_func($test, $a, $n); $result[$test] += (microtime(true) - $start);
        }
    }
}

asort($result);

echo '<pre>';
print_r($result);
echo '</pre>';

function testWithForeach($a, $n)
{
    foreach ($a as $key => $value)
    {
        if ($value >= $n)
        {
            $result = $key; break;
        }
    }

    return $result;
}

function testWithArrayFlip($a, $n)
{
    $a[] = $n; sort($a); $a = array_flip($a); return ($a[$n] - 1);
}

function testWithArraySearch($a, $n)
{
    $a[] = $n; sort($a); return (array_search($n, $a) - 1);
}

すべてのメソッドは同様の条件下で実行され、CPU時間全体に広がります。

$nステップとして10を使用して、0から1000までのすべての値をテストしました(合計100)。

$n/メソッドの組み合わせは10回実行され、得られた結果は次のとおりです。

Array
(
    [testWithForeach] => 19.338931560516
    [testWithArraySearch] => 96.209128856659
    [testWithArrayFlip] => 133.85276961327
)

なるべく公平を期しておりますが、実際の走行時間は状況により変動する場合がござい$nます。

于 2012-10-17T01:12:16.337 に答える
1

array_flip()を使用してこれを行うことができる場合があります。

[ghoti@pc ~]$ php -r '$n=150; $a=array(0,0,50,100,200,400,800); $a[]=$n; sort($a); $f=array_flip($a); print $f[$n]-1 . "\n";'
3
[ghoti@pc ~]$ php -r '$n=401; $a=array(0,0,50,100,200,400,800); $a[]=$n; sort($a); $f=array_flip($a); print $f[$n]-1 . "\n";'
5
[ghoti@pc ~]$ php -r '$n=200; $a=array(0,0,50,100,200,400,800); $a[]=$n; sort($a); $f=array_flip($a); print $f[$n]-1 . "\n";'
4
[ghoti@pc ~]$ php -r '$n=0; $a=array(0,0,50,100,200,400,800); $a[]=$n; sort($a); $f=array_flip($a); print $f[$n]-1 . "\n";'
1

これはどのように作動しますか?

分解してみましょう。

  • $n=0;私たちの番号。
  • $a=array(0,0,50,100,200,400,800);私たちの配列。
  • $a[]=$n;配列に番号を追加します...
  • sort($a);物を並べ替えて、番号を正しい位置に配置します...
  • $f=array_flip($a);次に、値をインデックスと交換します。
  • print $f[$n]-1そして、追加したアイテムの前のアイテムの値(以前のインデックス)を返します。

たとえば、例のように、$ aに同じ番号の複数のエントリが含まれていると、混乱する可能性があり0ます。-1これが発生した場合、インデックスは配列に1回しか表示されないため、調整を調整する必要がある場合があります(私の例では)。(たとえば、03回出現した場合は、で結果を調整する必要があります-2。この調整は追加のコードで追加できますが、その部分を自分で理解できると確信しています。:)

これによりループは回避されますが、の場合は注意が必要です$n=0

于 2012-10-17T01:30:33.910 に答える