Какой вариант быстрее - щас проверю PHP: <?php mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = "PHP - мова, яка може !бути! вбудована безпосередньо в html-код сторінок"; $randInverted = preg_replace_callback ("/([\p{L}\p{Nd}])/u", 'randInvert', $string); function invertCharCase ($c) { return ($c == mb_strtolower($c)) ? mb_strtoupper($c) : mb_strtolower($c); } function randInvert($m) { return rand(0, 1) ? invertCharCase($m[0]) : $m[0]; } // PhP - мОВА, яКа мОжЕ !БУТИ! ВБУДОВана безпосЕРедНьо В html-КОД СТОріНок echo $randInverted; ?>
preg мало того, что короче, так еще и быстрее: Код (Text): shock@shock:~/Web/www.tests.lh/htdocs$ cat strInvert.php <?php mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = "PHP - мова, яка може !бути! вбудована безпосередньо в html-код сторінок"; function caseInvert($string) { $nstr = ''; $c = mb_strlen($string); for ($i = 0; $i < $c; $i++) { $char = mb_substr($string, $i, 1); // if it's lower case make it upper case if ($char == mb_strtolower($char)) { $char = mb_strtoupper($char); // if it's upper than make it lower } else { $char = mb_strtolower($char); } $nstr .= $char; } return $nstr; } // randomly capilizes/uncaptilizes chars in a string function caseRand($string) { $nstr = ''; $c = mb_strlen($string); for ($i = 0; $i < $c; $i++) { $char = mb_substr($string, $i, 1); rand(0, 1) ? $char = caseInvert($char) : null; $nstr .= $char; } return $nstr; } $start = microtime (1); for ($i = 1000; $i--;) { $randInverted = caseRand($string); } echo (microtime(1) - $start), "\n"; ?>shock@shock:~/Web/www.tests.lh/htdocs$ php -f strInvert.php 0.651905059814 shock@shock:~/Web/www.tests.lh/htdocs$ php -f strInvert.php 0.716600894928 shock@shock:~/Web/www.tests.lh/htdocs$ php -f strInvert.php 0.689832925797 shock@shock:~/Web/www.tests.lh/htdocs$ cat pregInvert.php <?php mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = "PHP - мова, яка може !бути! вбудована безпосередньо в html-код сторінок"; function invertCharCase ($c) { return ($c == mb_strtolower($c)) ? mb_strtoupper($c) : mb_strtolower($c); } function randInvert($m) { return rand(0, 1) ? invertCharCase($m[0]) : $m[0]; } $start = microtime (1); for ($i = 1000; $i--;) { $randInverted = preg_replace_callback ("/([\p{L}\p{Nd}])/u", 'randInvert', $string); } echo (microtime(1) - $start), "\n"; ?>shock@shock:~/Web/www.tests.lh/htdocs$ php -f pregInvert.php 0.586416006088 shock@shock:~/Web/www.tests.lh/htdocs$ php -f pregInvert.php 0.577327013016 shock@shock:~/Web/www.tests.lh/htdocs$ php -f pregInvert.php 0.609392166138 shock@shock:~/Web/www.tests.lh/htdocs$ php -f pregInvert.php 0.552659988403 shock@shock:~/Web/www.tests.lh/htdocs$
Первое число - количество символов. Второе - время Код (Text): shock@shock:~$ php -f strInvert.php 10147 11.3335700035 shock@shock:~$ php -f strInvert.php 10147 11.2968318462 shock@shock:~$ php -f pregInvert.php 10147 25.1141960621 shock@shock:~$ php -f pregInvert.php 10147 24.9959099293 shock@shock:~$ php -f preg2Invert.php 10147 4.20771503448 shock@shock:~$ php -f preg2Invert.php 10147 4.31280899048 PHP: <?php /*********************** * strInvert.php ***********************/ mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = '...'; echo strlen($string) . ' '; function caseInvert($string) { $nstr = ''; $c = mb_strlen($string); for ($i = 0; $i < $c; $i++) { $char = mb_substr($string, $i, 1); // if it's lower case make it upper case if ($char == mb_strtolower($char)) { $char = mb_strtoupper($char); // if it's upper than make it lower } else { $char = mb_strtolower($char); } $nstr .= $char; } return $nstr; } // randomly capilizes/uncaptilizes chars in a string function caseRand($string) { $nstr = ''; $c = mb_strlen($string); for ($i = 0; $i < $c; $i++) { $char = mb_substr($string, $i, 1); rand(0, 1) ? $char = caseInvert($char) : null; $nstr .= $char; } return $nstr; } $start = microtime (1); for ($i = 100; $i--;) { $randInverted = caseRand($string); } echo (microtime(1) - $start), "\n"; ?> PHP: <?php /*********************** * pregInvert.php ***********************/ mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = '...'; echo strlen($string) . ' '; function invertCharCase ($c) { return ($c == mb_strtolower($c)) ? mb_strtoupper($c) : mb_strtolower($c); } function randInvert($m) { return rand(0, 1) ? invertCharCase($m[0]) : $m[0]; } $start = microtime (1); for ($i = 100; $i--;) { $randInverted = preg_replace_callback ("/([\p{L}\p{Nd}])/u", 'randInvert', $string); } echo (microtime(1) - $start), "\n"; ?> PHP: <?php /*********************** * preg2Invert.php ***********************/ mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = '...'; echo strlen($string) . ' '; function invertCharCase ($c) { return ($c == mb_strtolower($c)) ? mb_strtoupper($c) : mb_strtolower($c); } function randInvert($m) { return rand(0, 1) ? invertCharCase($m[0]) : $m[0]; } $start = microtime (1); for ($i = 100; $i--;) { $randInverted = preg_replace_callback ("/([\p{L}\p{Nd}])/", 'randInvert', $string); } echo (microtime(1) - $start), "\n"; // echo $randInverted; ?> Текст скачан с Яндекс-рефератов. Единственное отличие версии pregInvert от preg2Invert в модификаторе /u, который сейчас никак не влияет сейчас и вот доказательство: Код (Text): shock@shock:~$ php -f pregInvertMerge.php тестОВАя СтрокА hErE ТЕСТОвая строКа hErE shock@shock:~$ cat pregInvertMerge.php PHP: <?php mb_internal_encoding('UTF-8'); header('Content-type: text/plain; charset="utf-8"'); $string = "Тестовая строка here"; function invertCharCase ($c) { return ($c == mb_strtolower($c)) ? mb_strtoupper($c) : mb_strtolower($c); } function randInvert($m) { return rand(0, 1) ? invertCharCase($m[0]) : $m[0]; } echo preg_replace_callback ("/([\p{L}\p{Nd}])/u", 'randInvert', $string), "\n"; echo preg_replace_callback ("/([\p{L}\p{Nd}])/", 'randInvert', $string), "\n"; ?> UPD: (актуально для версии до 5.3)
таак-с. Вроде все правила в cangeCase должны работать. Обновление в репозитории я сделал мерж бранчей. Но у меня все равно два бранча. Я хочу удалить "another changeCase", оставить только default что б работать с ней. Как это сделать??
добавил ф-цию fill (в точности повторяет str_pad, разве что поддерживает и UNICODE) http://code.google.com/p/strclass/sourc ... ea07528298 Про репозиторий: не, ну это просто капец какой-то. Я не пойму, то ли это гугл тупит, то ли я. Я же сделал мерж, на графе видно, что он состоялся и как бы ветки слились. Почему же тогда у меня все равно 2 ветки? upd: все же то я дурак. Не туда смержил. Распределенные системы контроля версий весьма прикольны и нетривиальны.
Опечаточка: И в конце "encode64" чуть форматирование табами сбилось Код (Text): abstract class StrU extends StrCommon implements IStr Не понял, а зачем здесь abstract? Почему в take поиск по-умолчанию чувствительный к регистру, а в find - нечувствительный? Получается незакономерность и нестандартизованость
Предварительные тесты по оценке и сравнении скорости работы обертки и встроенных функций Цель - узнать потери при использовании обертки для действий, реализуемых встроенными функциями Софт: Код (Text): $ uname -sr Linux 2.6.28-11-generic $ php --version PHP 5.2.6-3ubuntu4.1 with Suhosin-Patch 0.9.6.2 (cli) (built: Apr 23 2009 14:35:05) Хард: Код (Text): Processor : 2x Intel(R) Core(TM)2 Duo CPU E4500 @ 2.20GHz Memory : 2061MB Вызов скрипта производился из консоли, на каждый тест - отдельный вызов. Листинги некоторых тестов приведены Тесты производились на ANSII функциях, потому вначале теста был вызван метод: Str::setMode(Str::ASCII); Так как класс находится в стадии разработки, к моменту релиза данная информация может существенно изменится и стать неактуальной. Потому публикуется исключительно в ознакомительных целях. Функции, которые производят отличный от встроенных в PHP(производят дополнительные вычисления) в тесте не учавствовали Ни одна переменная во время теста не пострадала. Время подключения файлов: IStr.php, StrA.php, StrU.php через require_once: 0.002 - 0.003 сек Если убрать абстракцию и оставить один подключаемый класс (например, только StrU), то время подключения можно сократить до 0.001-0.002 сек. Итак, строка длиной в 336 символов. Код (Text): # Core-функции $ php -f index.php 0.331629037857 $ php -f index.php 0.293648004532 $ php -f index.php 0.272671937943 # Полноценная обертка $ php -f index.php 1.15254306793 $ php -f index.php 1.3052110672 $ php -f index.php 1.11312699318 # Обертка - один класс $ php -f index.php 0.820480108261 $ php -f index.php 0.799670934677 $ php -f index.php 0.795886993408 Мы видим падение сторости выполнения строковых функций при использовании полноценной обертки в 4 раза и в 2,7 раза при использовании урезанной обертки. Теперь увеличим строку в 30 раз. Строка, длиной в 10080 символов: Код (Text): # Core-функции $ php -f index.php 2.82341599464 $ php -f index.php 2.56636095047 $ php -f index.php 2.54383087158 # Полноценная обертка $ php -f index.php 3.0574889183 $ php -f index.php 3.10743379593 $ php -f index.php 3.09924817085 # Обертка - один класс $ php -f index.php 2.87202906609 $ php -f index.php 2.58693885803 $ php -f index.php 2.69115591049 При такой большой строке время выполнения для полноценной обертки увеличилось на 16 процентов, а время выполнения урезанной обертки увеличилось на 2% Какой вывод можно сделать? Да, обертка ощутимо замедляет время выполнение для маленьких строк. Замедление составит 0.5-1 секунду при условии, что в скрипте будет вызвано 180000 строковых функций. Стоит учесть, что время выполнения строковых функций в реальном проекте составляет крайне малую долю от выполнения всех функций Еще не стоит забывать, что данная обертка расширяет возможности для работы со строками, которые, при надобности, все-равно придется писать и выносить в отдельный класс/функции Если для вас, несмотря на удобство использования, пару процентов увеличения скорости выполнения скрипта - крайне критичны, то рекомендую не использовать эту обертку, а еще лучше - подумать о переходе на ассемблер Функции: PHP: <?php // Встроенные функции $s = microtime(1); for($i=10000;$i--;) { stripos($string, 'string'); strripos($string, 'string'); strpos($string, 'string'); strrpos($string, 'string'); strstr($string, 'string'); stristr($string, 'string'); strtoupper($string); strtolower($string); ucfirst($string); ucwords($string); base64_encode($string); base64_decode($string); strlen($string); trim($string); ltrim($string); rtrim($string); strrev($string); str_pad('string', 400, $string, STR_PAD_BOTH); } echo microtime(1) - $s; $s = microtime(1); for($i=10000;$i--;) { Str::find('string', $string); // stripos Str::find('string', $string, Str::RIGHT); // strripos Str::find('string', $string, Str::LEFT, true); // strpos Str::find('string', $string, Str::RIGHT, true); // strrpos Str::take('string', $string, Str::RIGHT_WITH); // strstr Str::take('string', $string, Str::RIGHT_WITH, false); // stristr Str::changeCase($string); // strtoupper Str::changeCase($string, Str::ALL, Str::DOWN); // strtolower Str::changeCase($string, Str::FIRST); // ucfirst Str::changeCase($string, Str::TITLE); // ucwords Str::encode64($string); // base64_encode Str::decode64($string); // base64_decode Str::length($string); // strlen Str::trim($string); // trim Str::trim($string, NULL, Str::LEFT); // ltrim Str::trim($string, NULL, Str::RIGHT); // rtrim Str::reverse($string); // strrev Str::fill($string, 400, 'string', Str::BOTH); // str_pad } echo microtime(1) - $s;
TheShock абстракт - для того, что б никто не пытался создать его экземпляр опечатки - да. Они присутствуют. Я после тяжелого трудового дня как никак занимаюсь этой разработкой.
TheShock ээх, тест неутешителен. Нужно писать расширение на сях =) сможешь потом это и на utf-8 строках сделать?
Ничего - понемногу исправим. encode64 и decode64 в Ансии и Утф версиях одинаковы. Может, стоит совместить?
PHP: <? $s = microtime(1); for($i=10000;$i--;) { mb_stripos($string, 'string'); mb_strripos($string, 'string'); mb_strpos($string, 'string'); mb_strrpos($string, 'string'); mb_strstr($string, 'string'); mb_stristr($string, 'string'); mb_strtoupper($string); mb_strtolower($string); // ucfirst($string); // mb_convert_case($string, MB_CASE_TITLE); base64_encode($string); base64_decode($string); mb_strlen($string); // При UTF некорректно работает со вторым параметром: [url=http://habrahabr.ru/blogs/php/45886/]http://habrahabr.ru/blogs/php/45886/[/url] trim($string); ltrim($string); rtrim($string); // Отсутствует UTF-версия // strrev($string); // str_pad('string', 400, $string, STR_PAD_BOTH); } echo microtime(1) - $s; $s = microtime(1); for($i=10000;$i--;) { Str::find('string', $string); // stripos Str::find('string', $string, Str::RIGHT); // strripos Str::find('string', $string, Str::LEFT, true); // strpos Str::find('string', $string, Str::RIGHT, true); // strrpos Str::take('string', $string, Str::RIGHT_WITH); // strstr Str::take('string', $string, Str::RIGHT_WITH, false); // stristr Str::changeCase($string); // strtoupper Str::changeCase($string, Str::ALL, Str::DOWN); // strtolower // Str::changeCase($string, Str::FIRST); // ucfirst // Эта функция есть серьезным источником утечки времени. До выяснения обстоятельств и проверки на наркотики не учавствует в тесте // Str::changeCase($string, Str::TITLE); // ucwords Str::encode64($string); // base64_encode Str::decode64($string); // base64_decode Str::length($string); // strlen Str::trim($string); // trim Str::trim($string, NULL, Str::LEFT); // ltrim Str::trim($string, NULL, Str::RIGHT); // rtrim // Str::reverse($string); // strrev // Str::fill($string, 400, 'string', Str::BOTH); // str_pad } echo microtime(1) - $s; Код (Text): # 336 символов, 10000 проходов # core 7.73008608818 7.71576094627 7.6764550209 # wrapper 7.18259906769 7.70127987862 7.10522294044 # 10080 символов, 1000 проходов # core 6.93881106377 6.83931708336 6.88085699081 # wrapper 5.64292311668 5.64824509621 5.6463561058 Результаты для меня неожиданные. Стоит провести тесты и узнать, какая функция делает работу с UTF быстрее при использовании обертки Я подозреваю, что это find, так как она единственная не использует встроенные mb_strr?i?pos. Но пойдем с конца и проверим выполнение других функций Код (Text): # trim, ltrim, rtrim # core 0.030268907547 0.0301129817963 0.0310060977936 # wrapper 0.158612012863 0.137850046158 0.174755811691 # base64_encode, base64_decode, mb_strlen # core 0.0849959850311 0.0995881557465 0.104970932007 # wrapper 0.14021897316 0.163207054138 0.144799947739 # mb_strtoupper, mb_strtolower # core 2.32789087296 2.33057904243 2.52379703522 # wrapper 2.43806600571 2.45367383957 2.54189920425 # mb_strstr, mb_stristr # core 1.90595817566 1.79276394844 1.88715982437 # wrapper 0.459541082382 0.479822874069 0.454295158386 # Оппа, вот так неожиданность! # mb_strr?i?pos # core 3.6611559391 3.55436682701 3.61103510857 # wrapper 3.83161997795 3.81030297279 3.89326310158 Ожидания не оправдались. Код для повторения теста: PHP: <? $s = microtime(1); for($i=10000;$i--;) { mb_strstr($string, 'string'); mb_stristr($string, 'string'); } echo microtime(1) - $s; $s = microtime(1); for($i=10000;$i--;) { Str::take('string', $string, Str::RIGHT_WITH); // strstr Str::take('string', $string, Str::RIGHT_WITH, false); // stristr } echo microtime(1) - $s; Чуть позже гляну, чем это может быть вызвано.
дык эта, совместил еще утром, в 10 30 где-то http://code.google.com/p/strclass/sourc ... 4105fe51c# че-то я не понял резалты последнего теста
PHP: <?php header('Content-Type: text/html; charset=utf-8;'); $str = ' Голова моя машет ушами, Как крыльями птица. Ей на шее ноги Маячить больше невмочь. Черный человек, Черный, черный, Черный человек На кровать ко мне садится, Черный человек Спать не дает мне всю ночь. '; include_once 'class.Str.php'; echo $str, "\n\n\n"; var_dump( Str::take('садится', $str, Str::RIGHT), Str::take('садится', $str, Str::RIGHT_WITH), Str::take('садится', $str, Str::LEFT), Str::take('садится', $str, Str::LEFT_WITH), Str::take('черный', $str, Str::LEFT_WITH, false), Str::take('черный', $str, Str::LEFT_WITH, true), Str::take('синий', $str, Str::LEFT_WITH, true, true), Str::take('синий', $str, Str::LEFT_WITH, true, false) ); я багов не вижу
хыы... сдается мне, потому что она статика. Я сейчас врать не буду, у меня ночь уже, но попробуй переписать тест с использованием рандомных входящих данных.
добавлен метод format http://code.google.com/p/strclass/sourc ... ebd7d5100# это типа смесь sprintf и vsprintf ф-ция сама поймет второй аргумент массив или нет и обработает все.
ты когда filter перепишешь с нормальными константами? Format - хорошо. Но. если человек вызовет чтото типа Str::format(); , то ему вернется ошибка чтото типа: "Undefined index 0 on string 119" - не самая понятная Думаю, может сейчас хотя бы trigger_error'ы добавить, пока с форматом Exception'ов не определились?
Кхм .. а что это значит? В смысле как это название согласуется с тем, что она делает и что она делает? По названию непонятно.
Apple используется в ф-ции take. Значит взять то, что слева в месте с подстрокой. Str::take('садится', $str, Str::LEFT_WITH) // по идее должно выбрать все, что слева от слова садится вместе с этим словом а ваще это документируем TheShock та я по поводу фильтра еще ниче не решил. нефиг формат без аргументов вызывыть. Ты еще скажи что будет, если вместо стоки в Str::find я загоню объект.
Koc, ну так я и говорю: PHP: <? public static function format() { $args = func_get_args(); if (func_num_args() == 0) { trigger_error("нефиг Str::format без аргументов вызывать.", E_USER_WARNING); return; } if (func_num_args() > 1) {