for vs foreach vs while, что быстрее для перебора массивов в php - PullRequest
11 голосов
/ 05 декабря 2009

Какой из них самый быстрый для перебора массивов в php? или существует другой, который также быстрее перебирать массивы?

Ответы [ 6 ]

19 голосов
/ 05 декабря 2009

Даже если есть какая-либо разница, эта разница будет настолько мала, что не будет иметь никакого значения.

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

Итак, используйте:

  • как хочешь
  • все, что соответствует вашему стандарту программирования
  • все, что лучше всего подходит для вашего кода / приложения

Будет много других вещей, которые вы могли бы / должны оптимизировать, прежде чем думать о такой микрооптимизации.


А если вам действительно нужны цифры (даже если это просто для удовольствия) , вы можете сделать некоторые тесты и увидеть результаты на практике.

9 голосов
/ 31 июля 2012

Для себя я выбираю свой цикл на основе этого:

foreach

Используется при переборе массива, длина которого (или может быть) неизвестна.

for

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

while

Используется, когда вы перебираете массив с явной целью найти или активировать определенный флаг.

Теперь это правда, вы можете использовать цикл FOR как цикл FOREACH, используя count ($ array) ... так что в конечном итоге все сводится к вашим личным предпочтениям / стилю.

4 голосов
/ 28 июля 2015

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

Для предоставления результатов тестирования, чтобы продемонстрировать эффективность различных методов, используемых для итерации по массиву, от 1 to 10,000.

Результаты тестов различных версий PHP: https://3v4l.org/a3Jn4

while $i++: 0.00077605247497559 sec
for $i++: 0.00073003768920898 sec
foreach: 0.0004420280456543 sec
while current, next: 0.024288892745972 sec
while reset, next: 0.012929201126099 sec
do while next: 0.011449098587036  sec //added after terminal benchmark
while array_shift: 0.36452603340149 sec
while array_pop: 0.013902902603149 sec

Принимает во внимание индивидуальные звонки на count с while и for

$values = range(1, 10000);
$l = count($values);
$i = 0;
while($i<$l){
   $i++;
}

$l = count($values);
for($i=0;$i<$l;$i++){
}

foreach($values as $val){
}

Приведенные ниже примеры использования while демонстрируют, как это будет использоваться менее эффективно во время итерации.

При функциональной итерации по массиву и поддержании текущей позиции; while становится намного менее эффективным, так как next() и current() вызываются во время итерации.

while($val = current($values)){
    next($values);
}

Если текущее позиционирование массива не важно, вы можете вызвать reset() или current() до итерации.

$value = reset($values);
while ($value) {
    $value = next($values);
}

do ... while - это альтернативный синтаксис, который можно использовать также в сочетании с вызовом reset() или current() до итерации и перемещением вызова next() в конец итерации.

$value = current($values);
do{
}while($value = next($values));

array_shift также может быть вызван во время итерации, но это отрицательно сказывается на производительности, поскольку array_shift переиндексирует массив каждый раз, когда он вызывается.

while($values){
   array_shift($values);
}

В качестве альтернативы array_reverse может быть вызвано до итерации вместе с вызовом array_pop. Это позволит избежать повторного индексирования при вызове array_shift.

$values = array_reverse($values);
while($values) {
   array_pop($values);
}

В заключение, скорость while, for и foreach должна быть не вопросом, а вопросом, что делается внутри них для поддержания позиционирования массива.

Терминальные тесты выполняются на PHP 5.6.20 x64 CLI NTS: Test Results

2 голосов
/ 09 августа 2011

Правильно используется, хотя является самым быстрым, поскольку он может иметь только одну проверку для каждой итерации, сравнивая одну переменную $ i с другой переменной $ max и не вызывая дополнительных вызовов перед циклом (кроме установки $ max) или во время цикла (кроме $ i ++; что по сути делается в любом операторе цикла).

Когда вы начинаете неправильно его использовать (например, while (list ..)), вам лучше использовать foreach, конечно, так как каждый вызов функции не будет так оптимизирован, как тот, который включен в foreach (потому что этот предварительно оптимизирован) ).

Даже тогда array_keys () дает вам то же удобство использования, что и foreach, еще быстрее. И, кроме того, если вы работаете с 2d-массивами, самодельные 2d_array_keys позволят вам использовать метод намного быстрее, чем foreach, тогда можно использовать foreach (просто попробуйте указать следующий foreach в рамках первого foreach, что последний foreach имел <2d_array_keys ($ array)> в качестве ключей ---).

Кроме того, все вопросы, связанные с первым или последним элементом цикла, используют while ($ i

И

while ($people_care_about_optimization!==true){
 echo "there still exists a better way of doing it and there's no reason to use any other one";
}
1 голос
/ 05 декабря 2009

Сделайте контрольный тест.

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

  • Вы используете foreach для итерации массива, без целых чисел в качестве ключей.
  • Вы используете для для итерации массива с целые числа как ключи.
  • и т.д.
0 голосов
/ 07 марта 2016

Помните, что предварительная загрузка большого количества mysqli_result в удобный массив может поставить вопрос о том, лучше ли использовать for / foreach / while для циклического перемещения этого массива, но это неправильный вопрос о плохом решение, которое тратит много оперативной памяти.

Так что не стоит отдавать предпочтение этому:

function funny_query_results($query) {
    $results = $GLOBALS['mysqli']->query($query);
    $rows = [];
    while( $row = $results->fetch_object() ) {
        $rows[] = $results;
    }
    return $rows;
}

$rows = funny_query_results("SELECT ...");
foreach($rows as $row) { // Uh... What should I use? foreach VS for VS while?
    echo $row->something;
}

Прямой способ получения одного за другим mysql_result в простом while намного более оптимизирован:

$results = $mysqli->query("SELECT ...");
while( $row = $results->fetch_object() ) {
    echo $row->something;
}
...