Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Корректная обрезка строк

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: не обрезать слова по середине
StormMan
Отправлено: 10 Июня, 2010 - 18:49:10
Post Id


Новичок


Покинул форум
Сообщений всего: 6
Дата рег-ции: Июнь 2010  


Помог: 0 раз(а)




Всем привет!
Есть такой модуль обрезки строки, это плагин для Smarty, но используются обычные функции:

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. function smarty_modifier_truncate($string, $length = 80, $etc = '...',
  3.                                   $break_words = false, $middle = false)
  4. {
  5.     if ($length == 0)
  6.         return '';
  7.  
  8.     if (strlen($string) > $length) {
  9.         $length -= strlen($etc);
  10.         if (!$break_words && !$middle) {
  11.             $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
  12.         }
  13.         if(!$middle) {
  14.             return substr($string, 0, $length).$etc;
  15.         } else {
  16.             return substr($string, 0, $length/2) . $etc . substr($string, -$length/2);
  17.         }
  18.     } else {
  19.         return $string;
  20.     }
  21. }
  22. ?>


Проблема этого кода в том, что он неправильно работает с кодировкой utf-8, если символы отличаются от латиницы, и исходит эта проблема из-за того, что с многобайтными символами функция substr работать не умеет. Заменяю её на mb_substr:

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. function smarty_modifier_truncate($string, $length = 80, $etc = '...',
  3.                                   $break_words = false, $middle = false)
  4. {
  5.     if ($length == 0)
  6.         return '';
  7.  
  8.     if (mb_strlen($string, utf8) > $length) {
  9.     //if (strlen($string) > $length) {
  10.         $length -= mb_strlen($etc, utf8);
  11.         //$length -= strlen($etc);
  12.         if (!$break_words && !$middle) {
  13.             $string = mb_ereg_replace('/\s+?(\S+)?$/', '', mb_substr($string, 0, $length+1, utf8), utf8);
  14.             //$string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
  15.         }
  16.         if(!$middle) {
  17.             return mb_substr($string, 0, $length, utf8).$etc;
  18.             //return substr($string, 0, $length).$etc;
  19.         } else {
  20.             return mb_substr($string, 0, $length/2, utf8) . $etc . mb_substr($string, -$length/2, utf8);
  21.             //return substr($string, 0, $length/2) . $etc . substr($string, -$length/2);
  22.         }
  23.     } else {
  24.         return $string;
  25.     }
  26. }
  27. ?>


Остаётся одна проблема: слова обрезаются посередине, получается ерунда вроде "Слова обрезаются посе...". Подскажите, какие функции можно применить, чтобы текст обрезался правильно: "Слова обрезаются посередине...".

Буду очень благодарен за примеры!
 
 Top
JustUserR
Отправлено: 11 Июня, 2010 - 15:10:42
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




StormMan пишет:
Остаётся одна проблема: слова обрезаются посередине, получается ерунда вроде "Слова обрезаются посе...". Подскажите, какие функции можно применить, чтобы текст обрезался правильно: "Слова обрезаются посередине...".
Для того чтобы не обрезать слова по середине нужно определиться с символов который является границей слова это может быть пробел и знаки пунктуации - соответственно вы можете получить индекс $v последнего символа в вашей функции но саму строку не обрезать - а запустить цикл который будет по очереди проверять символы и если они не являются символами границы слова то прибавлять значение $v на единицу Соответственно когда цикл завершится то вы получите значение $v по которому можно обрезать подстроку
Похожую задачу можно решить и в регулярном выражении за счет функции просмотра вперед


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
ZeiZ
Отправлено: 11 Июня, 2010 - 16:07:54
Post Id



Частый гость


Покинул форум
Сообщений всего: 231
Дата рег-ции: Нояб. 2009  
Откуда: Москва


Помог: 0 раз(а)




PHP:
скопировать код в буфер обмена
  1.  
  2. $words = 20; // Количество слов которые надо вывести
  3. $text = explode(" ", $text);
  4. for ($i=0;$i<$words;$i++) $fraza = $fraza.$text[$i]." ";
  5. $fraza = $fraza."...";
  6.  
  7. echo($fraza);
  8.  


Это сходу, не проверял, но должно работать.

(Отредактировано автором: 11 Июня, 2010 - 16:09:19)

 
 Top
JustUserR
Отправлено: 11 Июня, 2010 - 16:15:05
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




ZeiZ пишет:
Это сходу, не проверял, но должно работать
Работать должно но для больших текстов это достаточно медленное и ресурсоемкое решение - ведь потребуется в два раза болье памяти поскольку будет создан массив со словами текста а также разбивка осуществляется достаточно медленно Именно поэтому лучше делать разбивку индуктивно - то есть сразу получить небольшую часть текста в заданных пределах и уже внутри нее выполнять определенные операции


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
ZeiZ
Отправлено: 11 Июня, 2010 - 16:22:13
Post Id



Частый гость


Покинул форум
Сообщений всего: 231
Дата рег-ции: Нояб. 2009  
Откуда: Москва


Помог: 0 раз(а)




JustUserR разумеется речь идёт о небольших текстах.
 
 Top
JustUserR
Отправлено: 11 Июня, 2010 - 16:57:38
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




ZeiZ пишет:
JustUserR разумеется речь идёт о небольших текстах.
В таком случае использование похожего алгортма весьма возможно только нужно учитываь не количетсво слов а количество символов - поэтому можно создать переменную в которой будет храниться результурующее значение и в цикле можно конкатериовать в нее по слову пока значение не превысит заданной длины
Также хорошо делать проверку на тот случай если входящий текст вообще не будет содержать пробелов (Если текст берется автоматически из какого-то источника) - и в таком случае нужно ввести принудительную длину по которой он будет образеться


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
ZeiZ
Отправлено: 11 Июня, 2010 - 17:13:50
Post Id



Частый гость


Покинул форум
Сообщений всего: 231
Дата рег-ции: Нояб. 2009  
Откуда: Москва


Помог: 0 раз(а)




JustUserR спасибо, поправлю свой код, проверю скорость, отпишу.
 
 Top
JustUserR
Отправлено: 13 Июня, 2010 - 12:46:03
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




ZeiZ пишет:
JustUserR спасибо, поправлю свой код, проверю скорость, отпишу.
Пожалуйста! Могу вам привести тот PHP-код на основе вашего - который лишен вышеукзаанного недостатка и некоторых семантических ошибок
PHP:
скопировать код в буфер обмена
  1. $symbs = 20; // Количество симловов которые надо вывести
  2. $fraza="";
  3. $words = explode(" ", $text);
  4. for($i=0;$i<count($words);$i++)
  5. {$nv_str=$fraza.$words[$i]." ";
  6. if(strlen($nv_str)<$symbs)
  7. {$fraza= $nv_str;}
  8. else {break;}
  9. }
  10. $fraza = $fraza."...";
  11. echo($fraza);
Если улучшать данную задачу далее то можно было бы проводить дополнительный синтаксический анализ текста - чтобы оно к примеру заканчивалось завершенным предложением или его частью - но это уже достаточно сложный грамматический анализ


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
dahelp
Отправлено: 08 Сентября, 2011 - 09:02:45
Post Id



Новичок


Покинул форум
Сообщений всего: 1
Дата рег-ции: Сент. 2011  


Помог: 0 раз(а)




JustUserR пишет:
Пожалуйста! Могу вам привести тот PHP-код на основе вашего - который лишен вышеукзаанного недостатка и некоторых семантических ошибок


"..." ставит! если текст меньше $symbs. Как дописать функцию, чтобы если $text < $symbs не дописывал "..."?
 
 Top
EuGen Администратор
Отправлено: 08 Сентября, 2011 - 09:06:40
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Пожалуйста, в новую тему - эта устарела
Тема закрыта!


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Хранение данных, их вывод и обработка »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB