Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

покритикуйте плиз обработчик текста (Maus)
Author Message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Thu Jul 22, 2010 12:47 am (написано за 11 минут 11 секунд)
   Post subject: покритикуйте плиз обработчик текста
Reply with quote

Чувствую, что мозг как-то плесенью порос. Или это паранойя?

Итак, задача:
  1. Есть словарь, примерно на 700 терминов.
  2. Есть текст, от четверти до половины страницы. То есть по объему близок к индексу словаря. В тексте могут встречаться термины.
  3. Термины в тексте надо найти и обернуть во что-то (в коде будет пример).
  4. Дополнительная сложность: термины частично пересекаются, например, есть "Агрегат" и "Агрегат покрасочный"
  5. UTF-8
Вопрос в следующем: код ниже - эффективное решение?

Пара комментариев:
  1. насчет замен на уникальные последовательности с последующей заменой обратно я читал чуть ли не здесь, но конкретнее вспомнить не могу
  2. строковые функции вместо регулярок - из-за utf8. Я проверял, регулярка вида "/\bабразив\b/i" на cp1251 работает, на utf8 - нет (даже с ключом /u). Конечно, можете перепроверить.
Сам код (от него пахнет Битриксом, не не сильно):
Code (php): скопировать код в буфер обмена
class wdDictionary
{
    private static (www.php.net/static) $textBlocks = null;
   
    /**
     *
     * обработать текст, вставив туда код для вызова подсказок о терминах
     * @param string $text
     * @return string обработанный текст
     */

    public static (www.php.net/static) function ProcessText($text)
    {
        if ( is_null (www.php.net/is_null)(self::$textBlocks) )
        {
            self::loadTextBlocks();
        }
       
        // дополним пробелами для облегчения поиска
        $text = ' '.$text.' ';
        $replaces = array (www.php.net/array)();
       
        foreach (self::$textBlocks as $term=>$value)
        {
            /*
             * длина строки, чтобы правильно вырезать
             * длина строки не зависит от регистра
             */

            $len = strlen (www.php.net/strlen)($term);
            $lastPos = strlen (www.php.net/strlen)($text)-1;
           
            // запоминаем смещение для ускорения процесса
            $offset = 0;
            do
            {
                $pos = stripos($text, $term, $offset);
                if ( $pos !== false )
                {
                    $piece = substr (www.php.net/substr)($text, $pos, $len);
                    $left = ($pos==0) ? ' ' : substr (www.php.net/substr)($text, $pos-1, 1);
                    $right = ( $pos+$len == $lastPos ) ? ' ' : substr (www.php.net/substr)($text, $pos+$len, 1);
                   
                    if( preg_match (www.php.net/preg_match)('/[^а-яё]/iu', $left) && preg_match (www.php.net/preg_match)('/[^а-яё]/iu', $right) )
                    {
                        /*
                         * Чтобы избежать двойных замен (типа <tag><tag>термин</tag></tag>.
                         * Очевидно, что одинаковым (регистро-зависимо!) ключам
                         * будут отвечать одинаковые замены.
                         *
                         */

                        $substitute = md5 (www.php.net/md5)($piece);
                        if ( !array_key_exists (www.php.net/array_key_exists)($substitute, $replaces) )
                        {
                            $replaces[$substitute] = $value['open'].$piece.$value['close'];
                        }
                        /*
                         * проблема substr_replace отмеряет по байтам => глючит на юникоде
                         * так что всё вручную
                         */

                        $text = substr (www.php.net/substr)($text, 0, $pos).$substitute.substr($text, $pos+$len);
                        $offset = $pos+32;
                    } else
                    {
                        // чтоб не зациклиться на корне слова
                        $offset = $pos+$len;
                    }
                }
            } while ( $pos !== false );
        }
               
        foreach ($replaces as $key=>$replace)
        {
            $text = str_replace (www.php.net/str_replace)($key, $replace, $text);
        }
       
        return $text;
    }
   
    /**
     *
     * сбрасывает блоки замен в начальное состояние
     */

    private static (www.php.net/static) function clearTextBlocks()
    {
        self::$textBlocks = null;
    }
   
    /**
     *
     * готовит блоки замен
     *
     * структура: ключ - термин в нижнем регистре, значение - хэш
     * структура значения: готовый PCRE-паттерн, префикс и суффикс для найденного
     * такая избыточность должна ускорить поиск
     * @return void
     */

    private static (www.php.net/static) function loadTextBlocks()
    {
        static (www.php.net/static) $matches = array (www.php.net/array)('.', '+',);
        static (www.php.net/static) $replaces = array (www.php.net/array)('\.', '\+',);
       
        if ( is_null (www.php.net/is_null)(self::$textBlocks) )
        {
            self::$textBlocks = array (www.php.net/array)();
            if(CModule::IncludeModule("iblock"))
            {
                $arSort = array (www.php.net/array) ( 'SORT'=>'ASC' );
                $arSelect = array (www.php.net/array)(
                    'iblock_id', 'id', 'name', 'PREVIEW_TEXT',
                );
                $arFilter = array (www.php.net/array)(
                    'IBLOCK_ID'=>WD_DICTIONARY_IBLOCK_ID,
                    'ACTIVE'=>'Y',
                );
               
                $res = CIBlockElement::GetList( $arSort, $arFilter, false, false, $arSelect );
               
                while ( $row = $res->Fetch() )
                {
                    $text = strip_tags (www.php.net/strip_tags)($row['PREVIEW_TEXT']);
                   
                    $text = str_replace (www.php.net/str_replace)('"', '&#34', $text);
                   
                    $key = strtolower (www.php.net/strtolower)($row['NAME']);
                    self::$textBlocks[ $key ] = array (www.php.net/array)(
                        'open'=>'<dfn title="'.$text.'">',
                        'close'=>'</dfn>',
                    );
                }
            }
        }
    }
}
Back to top
View user's profile Send private message
Миша Спларов
Участник форума



Joined: 17 Nov 2003
Posts: 821
Карма: 65
   поощрить/наказать

Location: Россия, Москва

PostPosted: Thu Jul 22, 2010 6:41 am (спустя 5 часов 53 минуты; написано за 1 минуту 15 секунд)
   Post subject:
Reply with quote

Quote:
Я проверял, регулярка вида "/\bабразив\b/i" на cp1251 работает, на utf8 - нет (даже с ключом /u).
Эмулируйте \b через (?<=\PL) и (?=\PL).
www.phpwact.org/php/i18n/utf-8#w_w_b_b_meta_characters
www.php.net/manual/en/regexp.reference.unicode.php
Back to top
View user's profile Send private message
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Thu Jul 22, 2010 12:17 pm (спустя 5 часов 36 минут; написано за 1 минуту 25 секунд)
   Post subject:
Reply with quote

Контрастная подсветка найденных слов поисковыми скриптами (forum.dklab.ru/viewtopic.php?t=11473)
Проблема не похожа на Вашу?

Оффтопом: видится мне, что с трудом переносите Вы дурной запах битрикса : )
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Jul 23, 2010 1:07 am (спустя 12 часов 50 минут; написано за 4 минуты 18 секунд)
   Post subject:
Reply with quote

новый монстрик той же породы:
Code (php): скопировать код в буфер обмена
<?php
/**
 *
 * AWP - Almighty Word Processor
 * @author Maus
 *
 */


class AWP
{
    private static (www.php.net/static) $blocks = null;
    private static (www.php.net/static) $text = '';
    private static (www.php.net/static) $unique = '=^_^=';
    private static (www.php.net/static) $replaces;
   
    public static (www.php.net/static) function clearBlocks()
    {
        self::$blocks = null;
    }
   
    public static (www.php.net/static) function setBlocks(&$a)
    {
        self::$blocks = is_string (www.php.net/is_string)($a) ? array (www.php.net/array)($a) : $a;
    }
   
    public static (www.php.net/static) function transform(&$text)
    {
        if( is_array (www.php.net/is_array)(self::$blocks) )
        {
            self::$text = $text;
            //
            self::setUnique();
            //
            self::$replaces = array (www.php.net/array)();
           
            //
            self::$text = ' '.self::$text.' ';
           
            foreach ( self::$blocks as $pattern=>$v )
            {
                self::$text = preg_replace_callback (www.php.net/preg_replace_callback)($pattern, "AWP::firstPass", self::$text);
            }
           
            // second pass
            self::$text = str_replace (www.php.net/str_replace)( array_keys (www.php.net/array_keys)(self::$replaces), self::$replaces, self::$text);
        }
       
        //
        return substr (www.php.net/substr)(self::$text, 1, -1);
    }
   
    public static (www.php.net/static) function firstPass(&$matches)
    {
        $k = self::$unique . md5 (www.php.net/md5)($matches[0]);
        if ( !array_key_exists (www.php.net/array_key_exists)($k, self::$replaces)  )
        {
            self::$replaces[$k] = '<dfn>'.$matches[0].'</dfn>';
        }
       
        return $k;
    }
   
    /*
    private static (www.php.net/static) function setUnique()
    {
        while ( strpos (www.php.net/strpos)(self::$text, self::$unique) !== false )
        {
            self::$unique = self::$unique . md5 (www.php.net/md5)(microtime (www.php.net/microtime)(1).rand());
        }
    }
}
и пример к нему:
Code (php): скопировать код в буфер обмена
<?php
header (www.php.net/header)("Content-Type: text/plain; charset=UTF-8");

require_once 'awp.php';

$text = 'Агрегат покрасочный агрегатного состояния почти абсолютно матовый агрегат.
 Агрегат покрасочный или агрегат покрасочный - разницы никакой.'
;
$blocks = array (www.php.net/array)(
    '/(?<=\PL)агрегат покрасочный(?=\PL)/ui' =>true,
    '/(?<=\PL)агрегат(?=\PL)/ui' =>true,
);
AWP::setBlocks($blocks);
$text = AWP::transform($text);
echo (www.php.net/echo) $text;
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Jul 23, 2010 1:08 am (спустя 50 секунд; написано за 50 секунд)
   Post subject:
Reply with quote

Rumata
похожа, но пункт 4 моей задачи всё портит.

Миша Спларов
ага, спасибо.

А к алгоритму ни у кого претензий нету, что ли?
Меня огорчает следующее:
  1. словарь уже больше текста (легким движением руки увеличился в 6 раз). То есть я большим утюжу маленькое
  2. может, уйти от склеек? резать текст на куски, и по каждому куску рекурсивно вызывать со следующим термином... Или это программазм?
Back to top
View user's profile Send private message
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Fri Jul 23, 2010 4:11 am (спустя 3 часа 2 минуты; написано за 6 минут 4 секунды)
   Post subject:
Reply with quote

Maus wrote:
похожа, но пункт 4 моей задачи всё портит.
Maus wrote:
4. Дополнительная сложность: термины частично пересекаются, например, есть "Агрегат" и "Агрегат покрасочный"
Я думаю, что если список будет отсортирован по убыванию, то проблема порчи четвертым пунктом частично исчезнет.

Посмотрел код по диагонали. По коду мне не понравилось, что постоянно одет пересчет хешей (с помощью md5) и вычисляется массив выделяемых фраз (если я правильно понял смысл метода loadTextBlocks). Может быть что-то можно закешировать (в файл, БД)?

Поправьте меня. $term и $piece суть одно и то же, за исключением регистра. Так?
Code (php): скопировать код в буфер обмена
    public static (www.php.net/static) function ProcessText($text)
    {
...
        foreach (self::$textBlocks as $term=>$value)
        {
            /*
             * длина строки, чтобы правильно вырезать
             * длина строки не зависит от регистра
             */

            $len = strlen (www.php.net/strlen)($term);
            $lastPos = strlen (www.php.net/strlen)($text)-1;
           
            // запоминаем смещение для ускорения процесса
            $offset = 0;
            do
            {
                $pos = stripos($text, $term, $offset);
                if ( $pos !== false )
                {
                    $piece = substr (www.php.net/substr)($text, $pos, $len);
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Jul 23, 2010 10:18 am (спустя 6 часов 6 минут; написано за 12 минут 45 секунд)
   Post subject:
Reply with quote

Rumata wrote:
проблема порчи четвертым пунктом частично исчезнет
в функции hilite - нет. Там вложенность тегов возникает независимо от порядка замен, типа
Code (html): скопировать код в буфер обмена
<dfn> (december.com/html/4/element/dfn.html)<dfn> (december.com/html/4/element/dfn.html)</dfn></dfn>
. Отсюда возня с двухпроходной обработкой.
Rumata wrote:
за исключением регистра. Так?
так.
Второй вариант уже на регулярках, Миша Спларов подсказал верный путь. Правда, я пока не мерял, что быстрее.
Rumata wrote:
По коду мне не понравилось, что постоянно одет пересчет хешей
мне тоже не нравится, но я упираюсь в сохранение регистра. Можно ввести сохранение предыдущего найденного образца и, если он не совпадает с текущим, то только тогда генерировать ключ. Это сократит количество вычислений md5(), если термин встречается несколько раз в одном регистре, плюс избавит от array_key_exists(). С другой стороны, в $replaces появятся разные ключи с одинаковыми значениями.
Rumata wrote:
вычисляется массив выделяемых фраз
точнее, суффикса и префикса для каждого кусочка. В первом варианте в
Code (php): скопировать код в буфер обмена
        foreach ($replaces as $key=>$replace)
        {
            $text = str_replace (www.php.net/str_replace)($key, $replace, $text);
        }
это какое-то затмение было, во втором уже одной строкой
Rumata wrote:
Может быть что-то можно закешировать (в файл, БД)?
С одной стороны, стоит кэш в память - loadTextBlocks() вызывается однократно за время работы скрипта. С другой стороны, код не определяет, как он будет использован - однократно (при правке текста) или многократно (при выводе). Если ты об этом.
Back to top
View user's profile Send private message
Миша Спларов
Участник форума



Joined: 17 Nov 2003
Posts: 821
Карма: 65
   поощрить/наказать

Location: Россия, Москва

PostPosted: Fri Jul 23, 2010 10:58 am (спустя 40 минут; написано за 7 минут 36 секунд)
   Post subject:
Reply with quote

У меня частично офтопные вопросы/предложения:
1. Почему регулярки в $blocks ключами, а не значениями?
2. «self::$text = ' '.self::$text.' ';» по-моему лишнее, у меня \PL реагировал на начало и конец строки в подобном случае.
3.
Code (php): скопировать код в буфер обмена
self::$text = str_replace (www.php.net/str_replace)( array_keys (www.php.net/array_keys)(self::$replaces), self::$replaces, self::$text);
можно компактнее:
Code (php): скопировать код в буфер обмена
self::$text = strtr (www.php.net/strtr)(self::$text, self::$replaces);
4. Зачем так усложнять ключ? Возьмите любой непечатный символ. Я обычно использую «¬» и колбеком потом возращаете просто «¬<итератор>¬». Меньше текста - быстрее работает, если это критично, конечно :-)

Last edited by Миша Спларов on Fri Jul 23, 2010 11:42 am; edited 1 time in total
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Jul 23, 2010 11:27 am (спустя 28 минут; написано за 5 минут 16 секунд)
   Post subject:
Reply with quote

Миша Спларов
  1. говорят, что поиск по ключу быстрее
  2. держите тест-кейс:
    Code (php): скопировать код в буфер обмена
    $text = "Абразив абразивного профиля иногда абсолютно матовый. Абразив абсолютно матового типа уныл.";
    echo (www.php.net/echo) preg_replace (www.php.net/preg_replace)('/(?<=\PL)абразив(?=\PL)/ui', '-_-', $text);
  3. снова спасибо. Я у себя еще одну глупость нашел. В loadTextBlocks была генерация регулярок в таком виде:
    Code (php): скопировать код в буфер обмена
    static (www.php.net/static) $matches = array (www.php.net/array)('.', '+',);
    static (www.php.net/static) $replaces = array (www.php.net/array)('\.', '\+',);
    $pattern = '/\b'.str_replace($matches, $replaces, $key ).'\b/ui';
    а надо так
    Code (php): скопировать код в буфер обмена
    //
    $pattern = '/(?<=\PL)'.str_replace('-', '\-', preg_quote (www.php.net/preg_quote)($key) ).'(?=\PL)/ui';
  4. речь про setUnique() ? Ну да, можно ограничиться ¬ или ¬¬¬¬¬¬¬¬¬.... Тот алгоритм просто легче запомнить (-:
Back to top
View user's profile Send private message
Миша Спларов
Участник форума



Joined: 17 Nov 2003
Posts: 821
Карма: 65
   поощрить/наказать

Location: Россия, Москва

PostPosted: Fri Jul 23, 2010 11:42 am (спустя 14 минут; написано за 5 минут 10 секунд)
   Post subject:
Reply with quote

  1. У вас нет поиска. А выглядеть будет попроще, как сам массив, так и foreach.
  2. Верно. А так работает:
    Code (php): скопировать код в буфер обмена
    preg_replace (www.php.net/preg_replace)('/(?<!\pL)(?!\pL)/ui', '-_-', $text);
    Как, собственно, и ожидается (ничего похожего на «слово» не находит, значит совпадение).
  3. А как сейчас класс полностью выглядит?
  4. Да, но всё же, когда идёт обратная замена вариант с непечатным символом(ами) будет чуточку быстрее (и не чуточку на больших объёмах) :-)
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Jul 23, 2010 5:36 pm (спустя 5 часов 53 минуты; написано за 1 минуту 24 секунды)
   Post subject:
Reply with quote

Миша Спларов wrote:
А как сейчас класс полностью выглядит?
ладно, перестану всех путать и выложу рабочий код. Все, что не относится к делу - вырезано.
Предыдущие варианты можно забыть
Code (php): скопировать код в буфер обмена
class wdDictionary
{
    private static (www.php.net/static) $blocks = null;
    private static (www.php.net/static) $text = '';
    private static (www.php.net/static) $unique = '=^_^=';
    private static (www.php.net/static) $replaces;
    private static (www.php.net/static) $currBlock;
   
    /**
     *
     * обработать текст, вставив туда код для вызова подсказок о терминах
     * @param string $text
     * @return string обработанный текст
     */

    public static (www.php.net/static) function ProcessText(&$text)
    {
        if( $text =='' )
        {
            return;
        }
        $time_start = microtime (www.php.net/microtime)(true);
       
        if ( is_null (www.php.net/is_null)(self::$blocks) )
        {
            self::loadTextBlocks();
        }
        $period = microtime (www.php.net/microtime)(true) - $time_start;
        echo (www.php.net/echo) " time: $period  ";
       
        if( is_array (www.php.net/is_array)(self::$blocks) )
        {
            self::$text = ' '.$text.' ';
            // ставим уникальную часть ключа
            self::setUnique();
            // сбрасываем контейнер замен
            self::$replaces = array (www.php.net/array)();
            $time_start = microtime (www.php.net/microtime)(true);
           
            $pattern = self::getMegaPattern();
           
            self::$text = preg_replace_callback (www.php.net/preg_replace_callback)($pattern, "wdDictionary::firstPass", self::$text);
           
            // second pass
            $text = strtr (www.php.net/strtr)(self::$text, self::$replaces);
        }
       
        $period = microtime (www.php.net/microtime)(true) - $time_start;
        echo (www.php.net/echo) " time: $period ";
        return $text;
    }
   
    /**
     * очистить блоки
     */

    public static (www.php.net/static)  function clearBlocks()
    {
        self::$blocks = null;
    }
   
    /**
     * установить текстовые блоки
     * @param mixed &$a строка или массив
     */

    public static (www.php.net/static) function setBlocks(&$a)
    {
        self::$blocks = is_string (www.php.net/is_string)($a) ? array (www.php.net/array)($a) : $a;
    }
       
    /**
     *
     * готовит блоки замен
     *
     * структура: ключ - термин в нижнем регистре, значение - хэш
     * структура значения: префикс и суффикс для найденного
     * такая избыточность должна ускорить поиск
     * @return void
     */

    private static (www.php.net/static) function loadTextBlocks()
    {
        self::$blocks = array (www.php.net/array)();
        if(CModule::IncludeModule("iblock"))
        {
            $arSort = array (www.php.net/array) ( 'SORT'=>'ASC' );
            $arSelect = array (www.php.net/array)(
                'iblock_id', 'id', 'name', 'PREVIEW_TEXT', 'PROPERTY_ALIASES',
            );
            $arFilter = array (www.php.net/array)(
                'IBLOCK_ID'=>WD_DICTIONARY_IBLOCK_ID,
                'ACTIVE'=>'Y',
            );
           
            $res = CIBlockElement::GetList( $arSort, $arFilter, false, false, $arSelect );
           
            while ( $row = $res->Fetch() )
            {
                $text = strip_tags (www.php.net/strip_tags)($row['PREVIEW_TEXT']);
               
                $text = str_replace (www.php.net/str_replace)('"', '&#34', $text);
               
                $key = strtolower (www.php.net/strtolower)( trim (www.php.net/trim)($row['NAME']) );
               
                self::$blocks[$key] = array (www.php.net/array)(
                    'open'=>'<dfn title="'.$text.'">',
                    'close'=>'</dfn>',
                );
               
                $aliases = explode (www.php.net/explode)('*', strtolower (www.php.net/strtolower)($row['PROPERTY_ALIASES_VALUE']) );
               
                // вгоняем алиасы (альтернативные написания)
                foreach ($aliases as $alias)
                {
                    $alias = trim (www.php.net/trim)($alias);
                    if ( $alias != '' )
                    {
                        self::$blocks[ strtolower (www.php.net/strtolower)($alias) ] =& self::$blocks[$key];
                    }
                }
            }
        }
    }
   
    /**
     * генерирует шаблон
     * @param string $text
     * @return string PCRE pattern
     */

    private static (www.php.net/static) function getPattern($text)
    {
        return ( version_compare (www.php.net/version_compare)(PHP_VERSION, '5.3.0', '>=') )
            ? '/(?<!\pL)'.preg_quote( strtolower (www.php.net/strtolower)(trim (www.php.net/trim)($text)) ).'(?!\pL)/ui'
            : '/(?<!\pL)'.str_replace('-', '\-', preg_quote (www.php.net/preg_quote)( strtolower (www.php.net/strtolower)(trim (www.php.net/trim)($text)) ) ).'(?!\pL)/ui';
    }
   
    /**
     * генерирует шаблон
     * @param string $text
     * @return string PCRE pattern
     */

    private static (www.php.net/static) function getMegaPattern()
    {
        $result = '/(?<!\pL)(';
        $fragments = array_keys (www.php.net/array_keys)( self::$blocks );
        $fragments = array_map (www.php.net/array_map)('preg_quote', $fragments);
        if ( version_compare (www.php.net/version_compare)(PHP_VERSION, '5.3.0', '<') )
        {
            $callback = create_function (www.php.net/create_function)('$v', 'return str_replace("-", "\-", $v);');
            $fragments = array_map (www.php.net/array_map)($callback, $fragments);
        }
        return $result . implode (www.php.net/implode)('|', $fragments). ')(?!\pL)/ui';
    }
   
    /**
     * Колбэк для self::ProcessText
     * @param &$matches
     * @return string
     */

    public static (www.php.net/static)  function firstPass(&$matches)
    {
       
        $k = self::$unique . md5 (www.php.net/md5)($matches[0]);
        if ( !array_key_exists (www.php.net/array_key_exists)($k, self::$replaces)  )
        {
            $currentBlock = self::$blocks[ strtolower (www.php.net/strtolower)($matches[0]) ];
            self::$replaces[$k]$currentBlock['open'] . $matches[0] . $currentBlock['close'];
        }
       
        return $k;
    }
   
    /**
     *
     * установка уникальной части ключа
     */

    private static (www.php.net/static) function setUnique()
    {
        while ( strpos (www.php.net/strpos)(self::$text, self::$unique) !== false )
        {
            self::$unique = self::$unique . md5 (www.php.net/md5)(microtime (www.php.net/microtime)(1).rand());
        }
    }
}


Last edited by Maus on Fri Jul 23, 2010 6:20 pm; edited 1 time in total
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Jul 23, 2010 6:18 pm (спустя 42 минуты; написано за 55 секунд)
   Post subject:
Reply with quote

обновлял.
переход от цикла к мегаПаттерну дал ускорение в 10 раз ( с 0.1 до 0.01 секунды).
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Mon Aug 09, 2010 2:39 pm (спустя 16 дней 20 часов 20 минут; написано за 2 минуты 3 секунды)
   Post subject:
Reply with quote

задача обновилась!
теперь еще надо учесть, что термины, будь они неладны, встречаются в alt и title - и там их трогать нельзя.
Пока вижу лобовой путь - обезопасить содержимое атрибутов, потом прогнать через обработчик, восстановить содержимое атрибутов. Есть варианты?
Back to top
View user's profile Send private message
Миша Спларов
Участник форума



Joined: 17 Nov 2003
Posts: 821
Карма: 65
   поощрить/наказать

Location: Россия, Москва

PostPosted: Mon Aug 09, 2010 3:22 pm (спустя 43 минуты; написано за 6 секунд)
   Post subject:
Reply with quote

Ваш вариант самый правильный.
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Tue Aug 24, 2010 1:15 am (спустя 14 дней 9 часов 53 минуты)
   Post subject:
Reply with quote


М

Ветка выделена в отдельную тему «разница в скорости работы strtr и str_replace»,
расположенную в форуме Разное :: PHP (24 Августа 2010, 02:15).
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML