Илья Кригоузов Привет, меня зовут Илья Кригоузов и я занимаюсь информационными технологиями с 2005 года. Под такими технологиями я понимаю довольно широкий круг вещей: сайты любой сложности, базы данных и клиент-серверные приложения.
Закончил МИРЭА по специальности «инженер-математик», практику проходил на концерне радиостроения ОАО «Вега».Работаю в Информационных системах для бизнеса, так же сотрудничал с АйТи-агенством.
В свободное время увлекаюсь фотографией. Найти меня вы можете:

1 мая 2011 г.

Умное обрезание строк в php

Для вывода осмысленного текста ссылки вместо стандартного «Далее» или «Подробнее» в тизере нужно было реализовать функцию, которая сможет урезать строку по словам. В необъятных просторах нашел готовое решение, но оно мне не понравилось, поэтому сделал свое. Чтобы не томить торопящихся сразу приведу реализацию:

function smart_cut($text, $words = 3, $separator = ' ')
{
    $current_pos = 0;
    for($i = 0; $i < $words; $i++)
    {
        $current_pos = strpos($text, $separator, ($current_pos + 1));
    }
    return substr($text, 0, $current_pos);
}
Принимает три параметра, обязательный только первый:
  1. Текст, над которым будет производиться манипуляция;
  2. Количество слов, после которого строка будет обрезана;
  3. Разделитель слов в исходном тексте.
Вернет функция строку. Кому интересны подробности и сравнения, прошу под кат.


Решение, которое было найдено, навскидку показалось не очень быстрым, поэтому я решил сделать свое. Вот такое решение предлагает Максим:

function maxsite_str_word($text, $counttext = 10, $sep = ' ') {
$words = split($sep, $text);
if ( count($words) < $counttext )
$text = join($sep, array_slice($words, 0, $counttext));
return $text;
}
Если описать суть решения maxsite_str_word, то звучит она так: создать массив, элементами которого являются все слова, переданные в качестве первого параметра, потом отобрать n первых элементов, соединить их в строку и вернуть ее. Очевидно, что если переданный текст будет достаточно большой, то такое решение будет работать медленно.

Чтобы подтвердить свое предположение я провел ряд тестов (порядка 400) на сравнение быстродействия. Условия проведения были одинаковы: два идентичных php-файла, отличающихся только функцией обрезки строк, в одной директории на одном сервере. Каждый тест проводился по пять раз. В качестве параметров для теста использовался различный объем обрабатываемого текста и количество слов, до которого он должен быть обрезан.

Результаты можно посмотреть в таблице. По сводному графику видно, что при увеличении объема обрабатываемого текста время выполнения функции maxsite_str_word значительно увеличивается, а в решении smart_cut время выполнения на протяжении практически всего теста остается на одной отметке.

К тому же в реализации maxsite_str_word используется функция split, которая устарела в PHP версии новее 5.3.0.

6 комментариев:

  1. Так будет красивее:

    function smart_cut($text, $words = 3) {
    $match = array();
    $r = preg_match("/^[^\s]+([\s]+[^\s]+){0,".($words-1)."}/", $text, $match);
    if ($r)
    return $match[0];
    return '';
    }

    ОтветитьУдалить
  2. Могу предположить, что из-за отсутствия циклов такое решение будет работать быстрее, однако мне всегда сложно было назвать регулярные выражения красивым решением. Может быть из-за неопытности.

    ОтветитьУдалить
  3. зачем регэкспы? только для красоты? а производительность то что упадет в 500 раз, это норм, да?

    ОтветитьУдалить
  4. >>if ( count($words) < $counttext )
    должен быть другой знак:
    if ( count($words) > $counttext )

    ОтветитьУдалить
  5. в первой функции не учитывается, что в строке может быть меньше слов

    ОтветитьУдалить