Что быстрее: in_array () или куча выражений в PHP?

Быстрее ли это сделать:

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

Или:

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

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

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

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

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

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

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

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

Редактировать:

Мои тайминги с кодом @ Owen (PHP 5.2.6 / windows):

 Time1: 1.33601498604 Time2: 4.9349629879 

Перемещение массива (…) внутри цикла, как в вопросе:

 Time1: 1.34736609459 Time2: 6.29464697838 

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

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

 $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 

Обратите внимание, что, как отметил 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, но не так быстро, как прямое сравнение.

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

Вот мой код:

 $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, вам просто нужно их использовать

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

  • набор «if» и «else ifs»,
  • «если» с набором «или» условий (как в исходных деталях сообщения), или
  • использование «in_array» с встроенным массивом «на лету»,

лучше,

следует иметь в виду, что выражение «switch» на языке 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» для таких ситуаций, но, к сожалению, нужно создавать структуру данных, а затем использовать предикат, предназначенный для этой структуры данных, а не иметь способ просто скажите это без этого накладных расходов.

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

 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"); }