如果值在数组

时间:2015-10-02 15:50:01

标签: php algorithm for-loop

我的算法中有一个非常密集的函数。

我想尽量让它尽可能高效。我不太在乎可读性或类似的东西。只是速度。

该功能的基础是采取一组卡片:

$card1, $card2, $card3, $card4, $card5, $card6, $card7

每张卡都是数值。

然后,我需要从上面的集合中删除一组值。

$ remove_values = array(1,4,3,8,12);

所以基本上,我需要做的是,如果$ card1到$ card7出现在Remove Values中,请将该卡设置为0.

我目前的职能:

foreach($remove_values as $value) {
    if($value === $card1) {
        $card1 = 0;
    }
    if($value === $card2) {
        $card2 = 0;
    }
    if($value === $card3) {
        $card3 = 0;
    }
    if($value === $card4) {
        $card4 = 0;
    }
    if($value === $card5) {
        $card5 = 0;
    }
    if($value === $card6) {
        $card6 = 0;
    }
    if($value === $card7) {
        $card7 = 0;
    }
}

这很有效。但我想知道是否有更快的方法呢?调用php函数非常密集,所以我试图减少这些调用的数量。

由于我的算法不得不循环数百万条结果,我真的试图减少毫秒。

6 个答案:

答案 0 :(得分:0)

请尝试使用功能in_array()

    if(in_array($card1, $remove_values)) {
        $card1 = 0;
    }
    if(in_array($card2, $remove_values)) {
        $card2 = 0;
    }
    if(in_array($card3, $remove_values)) {
        $card3 = 0;
    }
    if(in_array($card4, $remove_values)) {
        $card4 = 0;
    }
    if(in_array($card5, $remove_values)) {
        $card5 = 0;
    }
    if(in_array($card6, $remove_values)) {
        $card6 = 0;
    }
    if(in_array($card7, $remove_values)) {
        $card7 = 0;
    }

答案 1 :(得分:0)

我不知道这可能与其他答案或你自己在速度方面的功能相比如何,但它可能有所帮助。

    $cards=array(
        'card1' =>  1,
        'card2' =>  5,
        'card3' =>  6,
        'card4' =>  8,
        'card5' =>  10,
        'card6' =>  11,
        'card7' =>  12
    );  
    $remove_values = array(1,4,3,8,12); 

    function callback( &$item, $key, $removals ){
        if( in_array( $item, $removals ) ) $item=0; 
    }
    $result=array_walk( $cards, 'callback', $remove_values );
    if( $result ){
        echo '<pre>Cards:',PHP_EOL,print_r( $cards, true ),'</pre>';
    }

    /* Will output */

    Cards:
    Array
    (
        [card1] => 0
        [card2] => 5
        [card3] => 6
        [card4] => 0
        [card5] => 10
        [card6] => 11
        [card7] => 0
    )

答案 2 :(得分:0)

您可以在设置卡等于零后“中断”循环,因此您不会在此之后评估其余的情况。

您还可以尝试将卡值放入数组中,并在将它们设置为零时将其删除,这样当您处理卡片时,每次都会搜索较小的数组。如果您可以像C ++地图那样对值和卡进行排序,那么搜索的速度会更快。

答案 3 :(得分:0)

使用SplFixedArray会略微改善性能。

$remove_values = new SplFixedArray(15);
$remove_values[1] = true;
$remove_values[4] = true;
$remove_values[3] = true;
$remove_values[8] = true;
$remove_values[12] = true;

if ($remove_values[$card1]) $card1 = 0;
if ($remove_values[$card2]) $card2 = 0;
if ($remove_values[$card3]) $card3 = 0;
if ($remove_values[$card4]) $card4 = 0;
if ($remove_values[$card5]) $card5 = 0;
if ($remove_values[$card6]) $card6 = 0;
if ($remove_values[$card7]) $card7 = 0;

你说过要做百万次循环。如果removed_values没有改变,只改变了卡的值,你总是可以对remove值的数组进行一些预处理,这样就可以进一步提高速度。

这是速度性能比较(一百万次循环)

                    | Normal Array | SplFixedArray
 Pre-Processing     |  4.2 seconds | 1.2 seconds
 Normal             |  5 seconds   | 4.2 seconds

答案 4 :(得分:0)

这里的优化(在我的kludgy IDEONE.com测试中)快了25%。 对 remove_values 使用关联数组,然后执行键查找 isset 。 如果isset为true,我们要删除该值为TRUE - 1(0)&amp; cardValue = 0,但如果isset为false,我们希望将值保持为FALSE - 1(-1)&amp; cardValue = cardValue。这只是一些小问题,可以保留或清零卡值,而不必进行任何条件跳转。

$remove_values = array();
/* USE ASSOC. ARRAY */
for ($x = 0; $x <= 20; $x++) {
    $r = rand(2, 14);
    $remove_values[$r] = $r;
}
$card1 = rand(2, 14);
$card2 = rand(2, 14);
$card3 = rand(2, 14);
$card4 = rand(2, 14);
$card5 = rand(2, 14);
$card6 = rand(2, 14);
$card7 = rand(2, 14);
// Testing code
//
$card1 = (isset($remove_values[$card1]) - 1) & $card1;
$card2 = (isset($remove_values[$card2]) - 1) & $card2;
$card3 = (isset($remove_values[$card3]) - 1) & $card3;
$card4 = (isset($remove_values[$card4]) - 1) & $card4;
$card5 = (isset($remove_values[$card5]) - 1) & $card5;
$card6 = (isset($remove_values[$card6]) - 1) & $card6;
$card7 = (isset($remove_values[$card7]) - 1) & $card7;

如果你想弄乱它或尝试其他版本http://ideone.com/DDyQ4a

,那么这就是IDEONE

答案 5 :(得分:0)

我发现这是一个奇怪的挑战,所以我按照OP的说明运行了10,000次迭代并使用了计时器助手类。

<?php
    class TimingHelper {
        private $start;
        public function __construct() {
            $this->start = microtime(true);
        }
        public function start() {
            $this->start = microtime(true);
        }
        public function segs() {
            return microtime(true) - $this->start;
        }
        public function time() {
            $segs = $this->segs();
            $days = floor($segs / 86400);
            $segs -= $days * 86400;
            $hours = floor($segs / 3600);
            $segs -= $hours * 3600;
            $mins = floor($segs / 60);
            $segs -= $mins * 60;
            $microsegs = ($segs - floor($segs)) * 1000;
            $segs = floor($segs);

            return 
                (empty($days) ? "" : $days . "d ") . 
                (empty($hours) ? "" : $hours . "h ") . 
                (empty($mins) ? "" : $mins . "m ") . 
                $segs . "s " .
                $microsegs . "ms";
        }
    }

    $cards=array(
        'card1' =>  1,
        'card2' =>  5,
        'card3' =>  6,
        'card4' =>  8,
        'card5' =>  10,
        'card6' =>  11,
        'card7' =>  12
    );  
    $remove_values = array(1,4,3,8,12); 

    function callback( &$item, $key, $removals ){
        if( in_array( $item, $removals ) ) $item=0; 
    }

    $th = new TimingHelper;
    $results=array();

    for( $i=0; $i < 10000; $i++ ){
        $th->start();
        $result=array_walk( $cards, 'callback', $remove_values );
        $results[]=$th->time();
    }

    echo min( $results );
    /* Outputs */
    /*
        -> 0s 0.0138282775879ms
    */
?>