2015-10-02 5 views
-1

У меня есть функция, которая довольно интенсивна в моем алгоритме.Удалить значения, если они находятся внутри массива

Я хочу попытаться сделать это как можно более эффективным. Мне все равно, что читаемость или что-то в этом роде. Просто скорость.

В основе функции взять набор карт:

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

Где каждую карта является числовым значением.

Тогда у меня есть массив значений, которые необходимо удалить из приведенного выше набора.

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

Поэтому в основном то, что мне нужно сделать, это, если $ CARD1 до $ card7 появляется в удалении значений, установите эту карту 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 является интенсивным, поэтому я пытаюсь уменьшить количество этих вызовов.

Я буквально пытаюсь сбрить миллисекунды из-за того, что мой алгоритм должен пройти миллионы результатов.

+0

Есть ли $ карты внутри массива? –

+0

Посмотрите на [array_filter()] (http://php.net/array_filter) и другие функции массива, встроенные в php. – vascowhite

+0

@PedroLobito это не так, но это может быть. Добавление к большему количеству массивов вызывает дополнительные накладные расходы. – Patchesoft

ответ

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; 
    } 
+0

Думаю, это нужно будет проверить массив 7 раз, а не только один раз. –

+0

Да, это занимает 1,7 секунды дольше, чем моя текущая версия. Спасибо, хотя :) – Patchesoft

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 
    ) 
+0

Это медленнее, чем исходный код. –

0

Вы можете «разбить» цикл после установки карты равной нулю, поэтому после этого вы не будете оценивать остальные случаи.

Вы также можете попробовать положить ценности карты в массив, и удалить их, как они установлены в ноль, так как вы обрабатывать карты, которые вы разыскивающим меньший массив каждый раз. Если бы вы могли сортировать значения и карты, как на карте C++, то это было бы еще быстрее для поиска.

+0

Я пробовал использовать переключатель, но он не улучшает скорость. –

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 ​​не меняется, только значение карт изменяются, вы всегда можете сделать некоторые предобработки массив значений удалить так, что увеличит скорость еще больше.

Вот сравнение производительности скорость (один миллион цикл)

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

где вы получили 'SplFixedArray'? –

+0

@PedroLobito, http://php.net/manual/en/class.splfixedarray.php. Он доступен на PHP 5.3.0+ – invisal

+0

Вы пытались запустить свой код? Я пробовал это, и он ничего не делает, даже ошибка с 'error_reporting' включена. (Я PHP 5.4.45) –

0

Вот оптимизации, (в моем запутано тесте IDEONE.com) составляет 25% быстрее. Используйте ассоциативный массив для remove_values ​​ затем сделать ключ поиска IsSet. Если isset истинно, мы хотим удалить значение так TRUE - 1 (0) & cardValue = 0, но если isset false, мы хотим сохранить значение так FALSE - 1 (-1) & 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; 

Вот IDEONE, если вы хотите возиться с ним или попробовать другой вариант http://ideone.com/DDyQ4a

+0

Ive проверил исходный код, и мне потребовался мой сервер '0.051975250244141ms', а ваш' 0.11682510375977ms' –

+0

@PedroLobito - может быть, вы могли бы добавить этот «оригинальный код» в пример ideone.com, который я опубликовал, чтобы узнать, что такое несоответствие является. Зная ответ на такие вопросы, как (Сколько значений должен иметь файл remove_array?), Вероятно, будет полезно. –

+0

Вы должны проверить тайминги кода на локальном сервере или, по крайней мере, на сервере, который не загружен (в отличие от ideone), потому что тайминги могут отличаться. –

0

я нашел это любопытный вызов, поэтому я побежал 10000 итераций, как отмечает О.П. и использовать вспомогательный таймер класс.

<?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 
    */ 
?> 
Смежные вопросы