Intereting Posts
Yii2 DetailView: значение атрибута с использованием функции Как извлечь текст из изображения с помощью PHP Функция com_create_guid () получила ошибку на стороне сервера, но отлично работает в локальной сети, используя php Регулярное выражение извлекает переменную JavaScript в PHP Класс PHP: глобальная переменная как свойство в классе PHP-взаимодействие с кодировкой HTML Charset Можно ли передать переменную php внутри javascript? Как избежать «?» С использованием регулярного выражения в .htaccess для mod_rewrite Ошибка «Ссылка на объект, не установленная на экземпляр объекта», ошибка подключения к SOAP-серверу из PHP PHP – формат даты / времени Как передать значение в php из Android? PHP date_default_timezone_set () Форма html / php дает мне 500 ошибок внутреннего сервера при добавлении дополнительных полей ввода Ошибка mysql при вставке изображения в базу данных mysql Сортировка 3-мерного массива на 2-м уровне в зависимости от значений 3-го уровня

Разделить текст на проблемы слов PHP, сложная проблема

Я пытаюсь разделить текст на слова:

$delimiterList = array(" ", ".", "-", ",", ";", "_", ":", "!", "?", "/", "(", ")", "[", "]", "{", "}", "<", ">", "\r", "\n", '"'); $words = mb_split($delimiterList, $string); 

который отлично работает со строками, но я застрял в некоторых случаях, когда мне приходится делать цифры.

Например, если у меня есть текст «Посмотрите на это. Мой результат равен 3,14, и я доволен этим». Теперь массив

 [0]=>Look, [1]=>at, [2]=>this, [3]=>My, [4]=>score, [5]=>is, [6]=>3, [7]=>14, [8]=>and, .... 

Затем также 3.14 делится на 3 и 14, что не должно произойти в моем случае. Я имею в виду, что точка должна делить две строки, но не два числа. Это должно выглядеть так:

 [0]=>Look, [1]=>at, [2]=>this, [3]=>My, [4]=>score, [5]=>is, [6]=>3.14, [7]=>and, .... 

Но у меня нет идеи, как избежать подобных случаев!

Кто-нибудь знает, как решить эту проблему?

Танк, Гранит

Или используйте regex 🙂

 <?php $str = "Look at this.My score is 3.14, and I am happy about it."; // alternative to handle Marko's example (updated) // /([\s_;?!\/\(\)\[\]{}<>\r\n"]|\.$|(?<=\D)[:,.\-]|[:,.\-](?=\D))/ var_dump(preg_split('/([\s\-_,:;?!\/\(\)\[\]{}<>\r\n"]|(?<!\d)\.(?!\d))/', $str, null, PREG_SPLIT_NO_EMPTY)); array(13) { [0]=> string(4) "Look" [1]=> string(2) "at" [2]=> string(4) "this" [3]=> string(2) "My" [4]=> string(5) "score" [5]=> string(2) "is" [6]=> string(4) "3.14" [7]=> string(3) "and" [8]=> string(1) "I" [9]=> string(2) "am" [10]=> string(5) "happy" [11]=> string(5) "about" [12]=> string(2) "it" } 

Взгляните на strtok . Он позволяет динамически изменять токены синтаксического разбора, поэтому вы можете разбить строку вручную в цикле while, нажав каждое разделенное слово в массив.

Моя первая идея была preg_match_all('/\w+/', $string, $matches); но это дает аналогичный результат тому, который у вас есть. Проблема в том, что числа, разделенные точкой, очень неоднозначны. Это может означать как десятичную точку, так и конец предложения, поэтому нам нужен способ изменить строку таким образом, чтобы исключить двойной смысл.

Например, в этом предложении у нас есть несколько частей, которые мы хотели бы оставить как одно слово: "Look at this.My score is 3.14, and I am happy about it. It's not 334,3 and today's not 2009-12-12 11:12:13." ,

Мы начинаем с создания словаря search-> replace для кодирования исключений во что-то, что не будет разделено:

 $encode = array( '/(\d+?)\.(\d+?)/' => '\\1DOT\\2', '/(\d+?),(\d+?)/' => '\\1COMMA\\2', '/(\d+?)-(\d+?)-(\d+?) (\d+?):(\d+?):(\d+?)/' => '\\1DASH\\2DASH\\3SPACE\\4COLON\\5COLON\\6' ); 

Затем мы кодируем исключения:

 foreach ($encode as $regex => $repl) { $string = preg_replace($regex, $repl, $string); } 

Разделить строку:

 preg_match_all('/\w+/', $string, $matches); 

И преобразуйте закодированное слово назад:

 $decode = array( 'search' => array('DOT', 'COMMA', 'DASH', 'SPACE', 'COLON'), 'replace' => array('.', ',', '-', ' ', ':' ) ); foreach ($matches as $k => $v) { $matches[$k] = str_replace($decode['search'], $decode['replace'], $v); } 

$matches теперь содержит исходное предложение, разделенное на слова с правильными исключениями.

Вы можете сделать регулярное выражение, используемое в исключениях, простым или сложным, как вам нравится, но некоторая двусмысленность всегда будет проходить, например, два предложения с первым завершающим, а следующее, начинающееся с числа: Number of the counting shall be 3.3 only and nothing but the 3.5 is right out..

Используйте ". ", Вместо ".", В $delimiterList .