За последние 24 часа нас посетил 22491 программист и 1039 роботов. Сейчас ищут 665 программистов ...

удобная работа со строками [решение, рассуждение]

Тема в разделе "Решения, алгоритмы", создана пользователем Koc, 6 июн 2009.

  1. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Koc, ну что там?
     
  2. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    та работа-ебота, времени сейчас пока совсем мало. Давай план действий обрисуем, а я его выполню:
    1) обновить ф-цию take
    2) добавить size
    ...
     
  3. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    как минимум еще "replace" (ооочень часто используется). Ну и выше гдето в теме я говорил, каких функций не хватает.
     
  4. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    кстати, на счет array_get_range, чем тебя не устроила array_slice?
     
  5. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    http://code.google.com/p/strclass/source/list
    обновил маленько, а именно:
    изменен метод reverse, теперь второй параметр - длина строки, которую нужно отразить зеркально
    добавлен метод size для получения размера строки
    обновлен метод take. По идее повышение производительности =)

    далее: нужно разобраться с методом фильтра.
     
  6. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Код (Text):
    1. foreach ($what as $w) {
    foreach лучше таки, имхо, в таком классе не использовать (он работает с копией, а потому - дополнительные потери памяти, афаик). а использовать обратный for
    PHP:
    1. <?php
    2. for ($c = count($what); $c--;) {
    3.     $p = self::find($what[$c],
    имхо, в данном случае лучше малость пожертвовать очевидностью и легкостью коду в пользу быстродействия и уменьшения потребления памяти

    Медленный модификатор /u так и не убран.

    Предлагаю так. Можно еще добавить CSLASHES:
    PHP:
    1. <?php
    2.         public static function filter($string, $mode, $add = false)
    3.         {
    4.                 switch ($mode) {
    5.                     case self::SLASHES:
    6.                         return $add ?
    7.                             addslashes($string) :
    8.                             stripslashes($string);
    9.  
    10.                     case self::TAGS:
    11.                             return strip_tags($string);
    12.  
    13.                     case self::HTML:
    14.                         return $add ?
    15.                             htmlspecialchars_decode($string):
    16.                             htmlspecialchars($string);
    17.                 }
    18.         }
    19. ?>
     
  7. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    я тут делал автокомплит для консольного форума и сделал одну небольшую функцию, может и тут сделать?

    Код (Text):
    1. compare ($str1, $str2, $mode = Str::LEFT)
    2. $mode = [ Str::LEFT | Str::RIGHT | Str::FULL]
    Мне нужна была только Str::LEFT, но мало ли. Суть в следующем. Две строки сравниваются слева и выбирается одинаковый участок. Например:
    <?php
    compare('Картошка', 'Картограф'); // 'Карто'
    compare('Красная', 'Зеленая', Str::RIGHT); // 'ная'
    compare('Про рамы и окна', 'Программирование', Str::FULL); // 'Прорамн'
    ?>

    Код (Text):
    1. Про рамы и окна
    2. Программирование
    3. Про*рам******н** => Прорамн
    Не знаю, насколько нужен Str::FULL и Str::RIGHT - мне нужна была только Str::LEFT. Но, может, для того, чтобы узнать, насколько две строки отличаются?

    И вот метод сравнивания, который я писал для Str::LEFT

    PHP:
    1. <?php
    2. function compare ($str1, $str2) {
    3.     $result = '';
    4.     $L1 = strlen($str1);
    5.     $L2 = strlen($str2);
    6.     for ($k = 0; $k < $L1 and $k < $L2; $k++) {
    7.         if ($str1[$k] === $str2[$k]) {
    8.             $result .= $str1[$k];
    9.         } else {
    10.             break;
    11.         }
    12.     }
    13.     return $result;
    14. }
    15. ?>
     
  8. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Вы забывате, что в PHP реализован механизм copy-on-write, поетому foreach ничего не копирует.
     
  9. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    А работа с указателем не есть тем самым "write" ?
    Ну тогда все прекрасно :)
     
  10. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Koc, добавь, пожалуйста, в класс "class Str extends StrCommon implements IStr" следующий метод:
    Код (Text):
    1. public static function getMode() {
    2.     return self::$mb;
    3. }
     
  11. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Иха! Гугл исправил баг с отображением удаленных когда-то директорий в source view.
    http://code.google.com/p/strclass/sourc ... e15e6f8e1#

    фильтр сделал рекурсивный
    не тестил

    сравнением строк пока тоже еще не занимался.
     
  12. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Запостил issue на гугло коде
     
  13. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    ага, мне уведомление на почту пришло, сенг.
    вроде поправил. Когда делаем UP/DOWN для TITLE модификатор /u нельзя убирать, mb_strtoupper/mb_strtolower корежит строку

    по поводу mb_substr_count - бугого. Думал, что у нее такие же параметры как и у substr_count. Что ж, это только добавило плюсов к StrClass - у нас все параметры одинаковые, что для юникода, что для аскии.
     
  14. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    В сообщении на шестой странице я писал, что модификатор /u тут не нужен, приводя доказательство:
    PHP:
    1. <?php
    2. $string = "Тестовая строка here";
    3.  
    4. function invertCharCase ($c) {
    5.         return ($c == mb_strtolower($c))
    6.                 ? mb_strtoupper($c) : mb_strtolower($c);
    7. }
    8.  
    9. function randInvert($m) {
    10.         return rand(0, 1) ? invertCharCase($m[0]) : $m[0];
    11. }
    12.  
    13. echo preg_replace_callback ("/([\p{L}\p{Nd}])/u", 'randInvert', $string), "\n";
    14. echo preg_replace_callback ("/([\p{L}\p{Nd}])/", 'randInvert', $string), "\n";
    15. ?>
    Когда у меня был php 5.2.* - действительно работало без модификатора /u отлично.
    После проверки на php 5.3.0 был неприятно удивлён. Видимо в новой версии "пофиксили" этот кусок. Жалко
     
  15. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Но, должен сказать, пофиксили они его на славу:

    Код (Text):
    1.  = pregInvert 10000 =
    2. 3.954794883728
    3. 3.807187795639
    4.  
    5.  = strInvert 10000 =
    6. 15.424659967422
    7. 15.520486831665
    8.  
    9.  = pregInvert 500 =
    10. 0.18616509437561
    11. 0.20838403701782
    12.  
    13.  = strInvert 500 =
    14. 0.26548385620117
    15. 0.27108097076416
    PHP:
    1. <?php
    2. /***********************
    3.  * strInvert.php
    4.  ***********************/
    5.     mb_internal_encoding('UTF-8');
    6.     header('Content-type: text/plain; charset="utf-8"');
    7.  
    8.     $string = ''; // Строка
    9.  
    10.     echo mb_strlen($string) . ' ';
    11.  
    12.     function caseInvert($string) {
    13.         $nstr = '';
    14.         $c = mb_strlen($string);
    15.         for ($i = 0; $i < $c; $i++) {
    16.             $char = mb_substr($string, $i, 1);
    17.             // if it's lower case make it upper case
    18.             if ($char == mb_strtolower($char)) {
    19.                 $char = mb_strtoupper($char);
    20.             // if it's upper than make it lower
    21.             } else {
    22.                 $char = mb_strtolower($char);
    23.             }
    24.             $nstr .= $char;
    25.         }
    26.         return $nstr;
    27.     }
    28.        
    29.     // randomly capilizes/uncaptilizes chars in a string
    30.     function caseRand($string) {
    31.         $nstr = '';
    32.         $c = mb_strlen($string);
    33.         for ($i = 0; $i < $c; $i++) {
    34.             $char = mb_substr($string, $i, 1);
    35.             rand(0, 1) ? $char = caseInvert($char) : null;
    36.             $nstr .= $char;
    37.         }
    38.         return $nstr;
    39.     }
    40.  
    41.     $start = microtime (1);
    42.  
    43.     for ($i = 50; $i--;) {
    44.         $randInverted = caseRand($string);
    45.     }
    46.  
    47.     echo (microtime(1) - $start), "\n";
    48. ?>
    PHP:
    1. <?php
    2. /***********************
    3.  * pregInvert.php
    4.  ***********************/
    5.     mb_internal_encoding('UTF-8');
    6.     header('Content-type: text/plain; charset="utf-8"');
    7.  
    8.     $string = ''; // Строка
    9.  
    10.     echo mb_strlen($string) . ' ';
    11.  
    12.     function invertCharCase ($c) {
    13.         return ($c == mb_strtolower($c))
    14.             ? mb_strtoupper($c) : mb_strtolower($c);
    15.     }
    16.  
    17.     function randInvert($m) {
    18.         return rand(0, 1) ? invertCharCase($m[0]) : $m[0];
    19.     }
    20.  
    21.     $start = microtime (1);
    22.     for ($i = 50; $i--;) {
    23.         $randInverted = preg_replace_callback ("/([\p{L}\p{Nd}])/u", 'randInvert', $string);
    24.     }
    25.     echo (microtime(1) - $start), "\n";
    26. ?>
     
  16. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    да уж. Так я не понял, на 5.30 /u нужен везде или не нужен нигде?
     
  17. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Koc, в php 5.2.* [\p{L}\p{Nd}] работает корректно несмотря на модификатор /u
    В php 5.3.0 работает корректно только с этим модификатором.

    но в php 5.3.0 модификатор /u работает значительно быстрее.

    итог: надо ставить
     
  18. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    короче нужно вернуть все эти модификаторы на место?

    или можно вынести паттерны в переменные в common-классе и в зависимости от версии пыха менять значения этих переменных.
     
  19. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Koc, вообще паттерны желательно таки куда-то вынести. учитывая их повторяемость и необходимость обозначить, что этот паттерн значит.

    Думаю, не стоит парится, а делать с рассчетом на php 5.3 , но с поддержкой 5.2.
    С модификатором /u будет работать везде, а если человек сознательно не переходит на новую версию, то он должен понимать, что в 5.3 сделаны улучшения в плане скорости. В том числе в либах :)
     
  20. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Старался описать и, мне кажется, что filter таки не очень логичен.

    Вариант первый:
    $add заменить на $escape

    return $escape ? "строка экранировалась" : "строка деэкранировалась";

    потому что пока
    Код (Text):
    1. case self::SLASHES: return $add ? "Строка экранируется" : "Строка деэкранируется";
    2. case self::HTML   : return $add ? "Строка деэкранируется" : "Строка экранируется";
    Возможно, убрать третий параметр и вернутся к пяти константам (SLASHES, SLASHES_REMOVE, HTML, HTML_DECODE, TAGS)
    Второй вариант мне нравится больше.
     
  21. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Полностью обновил мануал. Добавил все методы кроме filter (не знаю, как описать). Особенно постарался с методом format =)

    Предлагаю оставить ссылку на проект на Гуглокоде и на мануал в первом сообщении.

    И предлагаю на главной странице проекта добавить несколько примеров. Чтобы разнообразить главную страницу :)
     
  22. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    окей, завтра сделаю, спасибо за руководство. Я начал писать его для класса-пагинатора - реально сложно.

    с фильтром огорчил. Изначально ж т было N констант. Ну и с паттернами завтра разберемся. Странно они делают: одно фиксят, другое ломают

    зы: я иногда просто давал бы отсылку на подобную функцию на пыхе. Например в том же формате прототипом служил sprintf, можно дать отсылку на все эти %d, %s. Хотя у тебя это подробней описано и примеров больше. И еще формат поддерживает массив в виде 2 аргумента.
     
  23. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    аха, я помню... работа над руководством очень помогает:
    1. Найти баги в коде - потому что пишешь много примеров
    2. Найти логические ошибки - потому что стараешься объяснить, а оно - не идет.
     
  24. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    и еще:
    да, я помню, что хорошо б сделать возможность обрезать по 1) кол-ву слов, 2) по буквам, но что б слова не резать.
    В какой метод это добавить и какими параметрами - вопрос.

    что там решили со сплитом, explode/implode? делать или это к массивам?

    что если в trim добавить возможность задавать charlist так, чтобы обрезались символы по умолчанию (пробелы) + указанные в чарлисте?
     
  25. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    ну да, я так и сделал, вобщем:
    а еще - по-русски