Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
На самом деле, второй способ работает медленнее! Особенно это кажется не очевидным для тех, кто имеет опыт программирования на C и C++, где индекс массива — это простое смещение указателя.Даже на C и C++ эксперименты с видами цикла (даже не окружающим контекстом и не содержимым!) — это последнее что придёт в голову делать в плане оптимизации по скорости, а на php это вообще смешно.
foreach часто выглядит элегантнее чем код с for, а если знать что он еще и быстрее, то это ли не повод взять за правило использование foreach как основного способа итерации.int zend_hash_index_find(const HashTable *ht, ulong h, void **pData)
{
uint nIndex;
Bucket *p;
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
if ((p->h == h) && (p->nKeyLength == 0)) {
*pData = p->pData;
return SUCCESS;
}
p = p->pNext;
}
return FAILURE;
}
<?php
$arr = range(0, 500000);
foreach ($arr as $i => $v);
$cnt = count($arr);
for ($i = 0; $i < $cnt; $i++) $v = $arr[$i];
$ php --version
PHP 5.4.24 (cli) (built: Jan 19 2014 21:32:15)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
$ php test.php
Foreach: 0.021 sec
For: 0.026 sec
$ php test2.php
Foreach: 0.029 sec (sum=125000250000)
For: 0.027 sec (sum=125000250000)
<?php
$arr = range(0, 500000);
$max = count($arr);
$sum = 0;
$start = microtime(true);
for($i = 0; $i < $max; $i++) $sum += $arr[$i];
echo "For took " . round(microtime(true) - $start, 3) . " sec\n";
$start = microtime(true);
foreach($arr as $i => $v) $sum += $v;
echo "Foreach_iv took " . round(microtime(true) - $start, 3) . " sec\n";
$start = microtime(true);
foreach($arr as $v) $sum += $v;
echo "Foreach_v took " . round(microtime(true) - $start, 3) . " sec\n";
$start = microtime(true);
$sum = array_sum($arr);
echo "Arrsum took " . round(microtime(true) - $start, 3) . " sec\n";
$ php test.php
For took 0.028 sec
Foreach_iv took 0.026 sec
Foreach_v took 0.023 sec
Arrsum took 0.008 sec
for($i = 0; $i < $n; $i++ ){...}
На каждой итерации ищет индекс во внутренней хэш таблице.
Оценочно, сложность последней операции выражалась бы суммой арифметической прогрессии n*(n+1)/2 т.е. и имела бы порядок O(n2), если бы при поиске значения по индексу перебиралась бы вся хэш таблица. На самом деле, перебираются не все значения, а только часть их, поэтому сложность будет варьироваться от O(n) до O(n2). И для больших массивов, она будет ближе к, O(n). Но даже в этом случае, перебор массива с доступом по ключу — более ресурсоемкая операция.
в php ЛЮБОЙ массив — хеш-таблицаСовершенно верно. Об этом и речь. Еще и двусвязный список. Я например не знал, что там внутри двусвязный список. И мне кажется это совсем не очевидно.
И для больших массивов, она будет ближе к, O(n)
for ($i = 0; $i<$len; $i+=2) {
for ($j = $len - 1; $j >=0; $j--) {
for ($k = $j; $k >=0; $k--) {
// это всё вы тоже форичем делаете?
}
}
}
$arr = [0 => 'a', 1 => 'b', 3 => 'c'];
$n = count( $arr );
for($k = 0; $k < $n; $k++ ) {...}
Сравнение производительности перебора массивов в цикле через for() и foreach()