2008-11-27 2 views
15

ли это быстрее сделать следующее:Что происходит быстрее: in_array() или куча выражений в PHP?

if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... } 

Или:

if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... } 

Есть целый ряд значений, при которых указывают, что это быстрее, чтобы сделать один или другой?

(В этом случае массив используется во втором варианте не alreay существует.)

+0

Непосредственная тема - вы только что удалили свой другой вопрос с нескольких минут назад, или я схожу с ума? – Greg 2008-11-27 21:45:32

ответ

14

я бы настоятельно рекомендую просто использовать in_array(), любая разница в скорости будет незначительной, но читаемость тестирования каждой переменной отдельно страшно.

просто для удовольствия вот тест я побежал:

$array = array('test1', 'test2', 'test3', 'test4'); 
$var = 'test'; 
$iterations = 1000000; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {} 
} 
$end = microtime(true); 

print "Time1: ". ($end - $start)."<br />"; 

$start2 = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, $array)) {} 
} 
$end2 = microtime(true); 

print "Time2: ".($end2 - $start2)."<br />"; 

// Time1: 1.12536692619 
// Time2: 1.57462596893 

слегка тривиальное замечание, чтобы наблюдать за, если $var не установлен, метод 1 занимает гораздо больше времени (в зависимости от того, сколько условий Вы проверяете)

+0

На какой версии PHP вы работаете? 5.2.6 (окна) дает Time1: 1.36 Time2: 4.88 - это большая разница – Greg 2008-11-27 21:38:40

+1

Также вы немного обманываете, выбирая массив (...) из цикла - если вы используете его, как говорит вопрос, мое время2 переходит на более чем 6 секунд – Greg 2008-11-27 21:40:11

+0

5.2.5 (mac os x), я получаю ~ 1.25: ~ 4 с не-читерской версией – Owen 2008-11-27 23:22:43

5

Первый будет быстрее - у второго есть много накладных расходов: создание массива, вызов функции, поиск массива ...

Однако, как я уже сказал в ответ на пару ответов, преждевременная оптимизация корень всего зла. Вы должны написать свой код для чтения, а затем , если нужно оптимизировать его профиль, а затем оптимизировать.

Edit:

Мои тайминги с @ кодом Оуэна (PHP 5.2.6/Windows):

Time1: 1.33601498604 
Time2: 4.9349629879 

Moving массив (...) внутри цикла, как и в вопросе:

Time1: 1.34736609459 
Time2: 6.29464697838 
2

in_array будет быстрее для большого количества предметов. «большой», будучи очень субъективным, основанным на множестве факторов, связанных с данными и вашим компьютером. Поскольку вы спрашиваете, я предполагаю, что вы не имеете дело с тривиальным количеством предметов. Для более длинных списков обратите внимание на this information и измерьте производительность с помощью перевернутого массива, чтобы php мог использовать хеш-поиск вместо линейного поиска. Для «статического» массива эта настройка может не улучшить производительность, но это также возможно.

Использование тестового кода Оуэна, с перевернутым массива и более итераций для более стабильных результатов:

$array2 = array_flip($array); 
$iterations = 10000000; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!isset($array2[$var])) {} 
} 
$end = microtime(true); 
print "Time3: ".($end - $start)."<br />"; 

Time1: 12.875 
Time2: 13.7037701607 
Time3: 3.70514011383 
6

Обратите внимание, что если вы хотите, чтобы заменить кучу !== заявления, вы должны пройти третий параметр in_array как true, который обеспечивает проверку типов элементов в массиве.

Обычное != не требует этого, очевидно.

1

Обратите внимание, что, как указал RoBorg, в создании массива есть накладные расходы, поэтому его необходимо перемещать внутри цикла итерации. По этой причине сообщение Sparr также мало вводит в заблуждение, так как накладные расходы с функцией array_flip.

Вот еще один пример со всеми 5 вариациями:

$array = array('test1', 'test2', 'test3', 'test4'); 
$var = 'test'; 
$iterations = 1000000; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {} 
} 
print "Time1: ". (microtime(true) - $start); 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, $array)) {} 
} 
print "Time2: ".(microtime(true) - $start); 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, array('test1', 'test2', 'test3', 'test4'))) {} 
} 
print "Time2a: ".(microtime(true) - $start); 

$array2 = array_flip($array); 
$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if (!isset($array2[$var])) {} 
} 
print "Time3: ".(microtime(true) - $start); 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    $array2 = array_flip($array); 
    if (!isset($array2[$var])) {} 
} 
print "Time3a: ".(microtime(true) - $start); 

Моими результаты:

Time1 : 0.59490108493 // straight comparison 
Time2 : 0.83790588378 // array() outside loop - not accurate 
Time2a: 2.16737604141 // array() inside loop 
Time3 : 0.16908097267 // array_flip outside loop - not accurate 
Time3a: 1.57209014893 // array_flip inside loop 

В заключении, используя array_flip (с IsSet) быстрее, чем inarray, но не так быстро, как прямое сравнение ,

1

Привет, я просто взял этот случай в крайности и указал, что при увеличении числа значений простое сравнение не самый результативный способ.

Вот мой код:

$var = 'test'; 
$num_values = 1000; 
$iterations = 1000000; 
print "\nComparison performance test with ".$num_values." values and ".$iterations." loop iterations"; 
print "\n"; 

$start = microtime(true); 
for($i = 0; $i < $iterations; ++$i) { 
    if ($var != 'test0' && 
     $var != 'test1' && 
     // ... 
     // yes I really have 1000 lines in my file 
     // ... 
     $var != 'test999') {} 
} 
print "\nCase 1: plain comparison"; 
print "\nTime 1: ". (microtime(true) - $start); 
print "\n"; 

$start = microtime(true); 
$array = array(); 
for($i=0; $i<$num_values; $i++) { 
    $array1[] = 'test'.$i; 
} 
for($i = 0; $i < $iterations; ++$i) { 
    if (!in_array($var, $array1)) {} 
} 
print "\nCase 2: in_array comparison"; 
print "\nTime 2: ".(microtime(true) - $start); 
print "\n"; 

$start = microtime(true); 
$array = array(); 
for($i=0; $i<$num_values; $i++) { 
    $array2['test'.$i] = 1; 
} 
for($i = 0; $i < $iterations; ++$i) { 
    if (!isset($array2[$var])) {} 
} 
print "\nCase 3: values as keys, isset comparison"; 
print "\nTime 3: ".(microtime(true) - $start); 
print "\n"; 

$start = microtime(true); 
$array = array(); 
for($i=0; $i<$num_values; $i++) { 
    $array3['test'.$i] = 1; 
} 
for($i = 0; $i < $iterations; ++$i) { 
    if (!array_key_exists($var, $array3)) {} 
} 
print "\nCase 4: values as keys, array_key_exists comparison"; 
print "\nTime 4: ".(microtime(true) - $start); 
print "\n"; 

Мои результаты (PHP 5.5.9):

Case 1: plain comparison 
Time 1: 31.616894006729 

Case 2: in_array comparison 
Time 2: 23.226133823395 

Case 3: values as keys, isset comparison 
Time 3: 0.050863981246948 

Case 4: values as keys, array_key_exists comparison 
Time 4: 0.13700890541077 

Я согласен, вот немного экстремальный, но он показывает общую картину и большой потенциал хэш-табличные ассоциативные массивы PHP, вам просто нужно использовать его

1

Говоря о PHP и спрашивая:

  • набор «если» s и «Else если»,
  • «если» с набором «или» условиях Ed (как в оригинальной почтовой детали), или
  • использование «in_array "с построенного массива на лету,

лучше,

следует иметь в виду, что PHP язык„заявление переключатель“является альтернативой, предназначенные для таких ситуаций и может быть лучшим ответом , (Хотя пример плаката приводит нас к простому сравнению двух решений, фактический вопрос заголовок просит рассмотреть in_array в сравнении с предложениями PHP, поэтому я считаю, что это честная игра).

В примере плаката, то я бы вместо того, чтобы рекомендовать:

switch ($var) 
{ case 'test1': case 'test2': case 'test3': case 'test4': 
    echo "We have a good value"; break; 
    default: 
    echo "We do not have a good value"; 
} 

Я хочу PHP разрешено в течение нескольких непримитивных конструкций в случаях, таких как запятая для «или». Но выше всего то, что разработчики PHP считают самым ясным способом справиться с этим. И, похоже, он более эффективен во время исполнения, чем другие две альтернативы.

До тех пор, пока я говорю о списке желаний, «IN», найденное в SQL, будет еще более ясным для ситуации примера для плаката.

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

0

Я знаю, что этот вопрос почти 10 лет, но есть и другие способы сделать это. Я использовал метод B от Nick's page с тысячами записей. Это было невероятно быстро.

foreach(array_values($haystack) as $v) 
    $new_haystack[$v] = 1; 
} 

// So haystack becomes: 
$arr[“String1”] = 1; 
$arr[“String2”] = 1; 
$arr[“String3”] = 1; 


// Then check for the key: 
if (isset($haystack[$needle])) { 
    echo("needle ".$needle." found in haystack"); 
}