Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Парсинг плейсхолдеров, Самый быстрый алгоритм? 
:(
    Опции темы
iNfantry
Дата 17.12.2013, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 17.9.2006

Репутация: нет
Всего: нет



Всем привет, задался спортивным интересом найти самый быстрый и оптимальный алгоритм для решения одной очень простой и банальной задачи - парсинг плейсхолдеров. Не имеет значения каких именно и для чего, возьмем самый простой вариант наподобие того что используется в функции pritnf() из языка Си:

Код

a = "aaa"; b = 25;
printf('Значение строковой переменной а: %s, значение числовой переменной b: %i', a, b);


Конкретно язык Си значения здесь не имеет, пусть мы хотим сделать собственную функцию на PHP, которая принимала бы также строку с форматом и пускай для простоты массив с переменными для подстановки вместо переменного числа аргументов. 
Лично я могу это сделать достаточно большим числом способов, но хотелось бы знать, возможно уже есть какое-то общепринятое решение (алгоритм) который быстрее всех остальных вариантов и является негласным стандартом?

Вобщем приведу парочку своих способов, а вы подскажите мне, можно ли сделать  еще лучше.

Способ 1:
Под рукой кода нет, давно так делал и уже не осталось примера, но суть такая: разбиваем форматную строку explode'ом по маркеру '%' и затем в цикле обрабатываем куски полученного массива и клеим строку с результатом, как нам надо.

Способ 2:
Код

public function parse($str, array $vars)
{
    $result  = '';
    $sz = sizeof($vars)-1;
    $i  = $offset = $new_pos = 0;

    while (($pos=strpos($str, '%', $offset)) !== false)
    {
        if ($str[$pos+1]=='%')
        {
            $new_pos++;
        }
        if ($i - $new_pos > $sz)
        {
            $this->error = 'count of vars and count of tags not match!';
            return false;
        }
        $result .= substr($str, $offset, $pos-$offset);
        $offset = $pos+2;
        switch ($str[$pos+1])
        {
            case 'i': $result.='\''.intval($vars[$i-$new_pos]).'\''; //обрабатываем как-то маркер %i
            break;
            case 'u': $result.='\''.abs(intval($vars[$i-$new_pos])).'\''; //обрабатываем как-то маркер %u
            break;
            case 's': $result.='\''.strval($vars[$i-$new_pos]).'\''; //обрабатываем как-то маркер %s
            break;
            default: $result.=$vars[$i-$new_pos];
        }
        $i++;
    }
    $result.=substr($str, $offset);

    return $result;
}

PM MAIL   Вверх
Fortop
Дата 17.12.2013, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(iNfantry @  17.12.2013,  22:06 Найти цитируемый пост)
Лично я могу это сделать достаточно большим числом способов, но хотелось бы знать, возможно уже есть какое-то общепринятое решение (алгоритм) который быстрее всех остальных вариантов и является негласным стандартом?

Сам printf наличествующий больше чем в 3х языках ни о чем не говорит?

А вообще гуглить в сторону
http://en.wikipedia.org/wiki/Commentz-Walter_algorithm
http://en.wikipedia.org/wiki/Aho%E2%80%93C...ching_algorithm


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
iNfantry
Дата 17.12.2013, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 17.9.2006

Репутация: нет
Всего: нет



Я вобще-то имел в виду общий случай и реализацию конкретно на ПХП, а функцию printf() чисто как пример!
Другой пример задачи - допустим подстановка значений в MySQL запрос по тому же принципу, чтобы потом секурно обработать переданные переменные.
Погуглил алгоритм Комменц-Вальтера - честно скажу не очень понимаю, когда мануал выглядит в виде сплошных математических выражений и символов, но предполагаю что реализация в таком виде кода на PHP, с кучей циклов и условных операторов будет крайне неэффективным решением, так как подобный код на PHP выполняется заведомо медленно, другое дело прикладные языки типа того же Си или Паскаля - на них можно делать такие алгоритмы. Возвращаясь к моему примеру - у меня есть класс в котором есть такой метод для парсинга и выполняется он ОЧЕНЬ часто, потому я ищу максимально эффективный вариант для PHP. К сожалению реализацию алгоритма Комменц-Вальтера на PHP я также не нашел, потому хотелось бы более конкретных ответов, а лучше примеров на PHP.
PM MAIL   Вверх
Sanchezzz
Дата 18.12.2013, 01:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



обычно все сводится к 
Код

$replace = [
   ':attr1' => 'Значение 1',
   ':attr2' => 'Значение 2',
];

$subject = ':attr1 - :attr2 ';
echo str_replace(array_keys($replace), array_values($replace), $subject);


способ 2 мне не совсем понятен, зачем ?


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
Fortop
Дата 18.12.2013, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(iNfantry @  17.12.2013,  23:17 Найти цитируемый пост)
так как подобный код на PHP выполняется заведомо медленно, другое дело прикладные языки типа того же Си

Поэтому пользуемся printf и не парим мозг себе



--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
baldina
Дата 18.12.2013, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



iNfantry, полагаю наиболее быстрым будет использование встроенных средств php
Код

$a = 'aaa'; $b = 25;
echo "Значение строковой переменной а: {$a}, значение числовой переменной b: {$b}";



Это сообщение отредактировал(а) baldina - 18.12.2013, 15:36
PM MAIL   Вверх
iNfantry
Дата 18.12.2013, 18:27 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 17.9.2006

Репутация: нет
Всего: нет



Жесть, я не понимаю людей, которые читают сообщения справа налево по диагонали и советуют какой-то бред.
Большое спасибо Sanchezzz за ответ ПО ТЕМЕ. Хорошая идея с str_replace(), но есть недостаток - придется указывать переменные в форматной строке с учетом ее номера, это первое, а второе - придется еще раз задавать массив с указанием что на что менять. Хочется просто сделать функцию: 

Код

parse('bla %s bla %i bla %s bla', array($a, $b, $c));


Способ 2, который я сказал это один из примеров решения задачи КОТОРЫЙ ВИЖУ Я. Естественно не считаю себя самым умным и думаю что другие придумали способ эффективнее, именно его я и хочу здесь увидеть)) Это ответ также и тем, кто советует использовать "встроенный printf()", читайте пожалуйста сообщения полностью, прежде чем отвечать на них!
PM MAIL   Вверх
baldina
Дата 18.12.2013, 19:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



iNfantry, php сам себе шаблонизатор. поэтому ответы, которые вам дали, неудивительны.
однако, если так хотите...
Код

function parse ($format, array $args) {
  $types = ['i'=>'int', 's'=>'string'];

  return preg_replace_callback ('/(%\w)/', function ($matches) use (&$args, $types) {
      
      $arg = array_shift ($args);
      if (settype ($arg, $types[$matches[1][1]]))
        return $arg;
      else {
        array_unshift ($args, $arg);
        return $matches[0];
      }
  }

  , $format);
}


Это сообщение отредактировал(а) baldina - 18.12.2013, 19:23
PM MAIL   Вверх
iNfantry
Дата 18.12.2013, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 17.9.2006

Репутация: нет
Всего: нет



Цитата(baldina @ 18.12.2013,  19:06)
iNfantry, php сам себе шаблонизатор. поэтому ответы, которые вам дали, неудивительны.
однако, если так хотите...
Код

function parse ($format, array $args) {
  $types = ['i'=>'int', 's'=>'string'];

  return preg_replace_callback ('/(%\w)/', function ($matches) use (&$args, $types) {
      
      $arg = array_shift ($args);
      if (settype ($arg, $types[$matches[1][1]]))
        return $arg;
      else {
        array_unshift ($args, $arg);
        return $matches[0];
      }
  }

  , $format);
}

Уоу, не знал таково (preg_replace_callback) ) То что надо! И еще раз - я не пишу замену принтф(), у меня совершенно другая задача, а принтф() просто крайне удачный пример. Большое спасибо, жаль + не могу поставить.

ЗЫ: Про подобный синтаксис "встраивания" функций (function ($matches) use (&$args, $types)) тоже не знал! Прям как в яваскрипте, очень удобно! Когда эта возможность появилась в PHP и Где почитать? Упустил начисто.

Это сообщение отредактировал(а) iNfantry - 18.12.2013, 19:44
PM MAIL   Вверх
baldina
Дата 18.12.2013, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(iNfantry @  18.12.2013,  19:39 Найти цитируемый пост)
Когда эта возможность появилась в PHP и Где почитать?

в 5.3 http://www.php.net/manual/ru/functions.anonymous.php
PM MAIL   Вверх
Fortop
Дата 19.12.2013, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(iNfantry @  18.12.2013,  18:27 Найти цитируемый пост)
Это ответ также и тем, кто советует использовать "встроенный printf()", читайте пожалуйста сообщения полностью, прежде чем отвечать на них! 


Чукча же ведь не читатель...
Цитата(iNfantry @  17.12.2013,  22:06 Найти цитируемый пост)
Конкретно язык Си значения здесь не имеет, пусть мы хотим сделать собственную функцию на PHP

Цитата(iNfantry @  17.12.2013,  22:06 Найти цитируемый пост)
возможно уже есть какое-то общепринятое решение (алгоритм) который быстрее всех остальных вариантов и является негласным стандартом?

Цитата(iNfantry @  17.12.2013,  23:17 Найти цитируемый пост)
но предполагаю что реализация в таком виде кода на PHP, с кучей циклов и условных операторов будет крайне неэффективным решением, так как подобный код на PHP выполняется заведомо медленно


Прочитать что цитируемый дурак ставит два противоречащих условия осознать самому мозгов не хватило?

Быстрейшие и универсальные алгоритмы это те, на которые дали вам ссылки в вики.
То, что у вас, внезапно, появилось строгое ограничение "должно быть сделано только на пхп и обязательно через жопу" это, конечно же, проблемы отвечающих....  smile 



--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
iNfantry
Дата 19.12.2013, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 17.9.2006

Репутация: нет
Всего: нет



Цитата(Fortop @ 19.12.2013,  11:19)
Цитата(iNfantry @  18.12.2013,  18:27 Найти цитируемый пост)
Это ответ также и тем, кто советует использовать "встроенный printf()", читайте пожалуйста сообщения полностью, прежде чем отвечать на них! 


Чукча же ведь не читатель...
Цитата(iNfantry @  17.12.2013,  22:06 Найти цитируемый пост)
Конкретно язык Си значения здесь не имеет, пусть мы хотим сделать собственную функцию на PHP

Цитата(iNfantry @  17.12.2013,  22:06 Найти цитируемый пост)
возможно уже есть какое-то общепринятое решение (алгоритм) который быстрее всех остальных вариантов и является негласным стандартом?

Цитата(iNfantry @  17.12.2013,  23:17 Найти цитируемый пост)
но предполагаю что реализация в таком виде кода на PHP, с кучей циклов и условных операторов будет крайне неэффективным решением, так как подобный код на PHP выполняется заведомо медленно


Прочитать что цитируемый дурак ставит два противоречащих условия осознать самому мозгов не хватило?

Быстрейшие и универсальные алгоритмы это те, на которые дали вам ссылки в вики.
То, что у вас, внезапно, появилось строгое ограничение "должно быть сделано только на пхп и обязательно через жопу" это, конечно же, проблемы отвечающих....  smile

В чем противоречие? Я описал задачу на примере принтф(), что мне нужно сделать на PHP алгоритм обработки подобной форматной строки. Я как мог пытался донести это из сообщения в сообщение, но понял меня только товарищ с ником baldina, за что ему огромное спасибо.
PM MAIL   Вверх
_zorn_
Дата 20.12.2013, 02:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1076
Регистрация: 21.8.2007

Репутация: 6
Всего: 12



sprintf, не?
Так и не понял зачем придумывать новый лисапед. Ты задачу внятнее объясни, а то "хочу свой принтф с блекджеком" как то в не то.
А вообще посмотри в сторону preg_replace с модификатором e в регулярке.

Это сообщение отредактировал(а) _zorn_ - 20.12.2013, 02:38
PM MAIL   Вверх
iNfantry
Дата 20.12.2013, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 17.9.2006

Репутация: нет
Всего: нет



Цитата(_zorn_ @ 20.12.2013,  02:36)
sprintf, не?
Так и не понял зачем придумывать новый лисапед. Ты задачу внятнее объясни, а то "хочу свой принтф с блекджеком" как то в не то.
А вообще посмотри в сторону preg_replace с модификатором e в регулярке.

Ок, еще раз - у меня есть класс, в котором есть метод который определенным образом парсит строку, тоесть подставляет в нее переменные, обрабатывая их определенным образом соответствующим их типу, в зависимости от форматной строки. Просто для удобства я выбрал синтаксис как у printf(), мог выбрать и любой другой, например 'bla {i} bla {s} bla {i}' или 'ololo #s ololo #i blablabla #s'. ВСЁ. smile И тем не менее - preg_replace_callback() который мне посоветовали - самый быстрый способ?
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0559 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.