|
|
|
| Очень нуждаюсь в пояснении к решению очередной задачи из книги авторов сайта "PHP 5 на примерах". Задача 5.2 со стр.158.
Текст задачи:
"Возьмите любой объемный текст, содержащий несколько предложений, и поместите каждое предложение текста в элементы массива $text так, чтобы первое предложение оказалось в элементе с индексом 0 - $text[0], второе в элементе с индексом 1 - $text[1] и т.д.
Далее, в цикле foreach преобразуйте массив $text в двумерный массив таким образом, чтобы в элементе $text[0][0] хранилось первое слово первого предложения, в элементе $text[0][1] хранилось второе слово первого предложения и т.д.
Проконтролируйте результаты работы, отправив дамп массива в окно браузера при помощи функции print_r()."
Я решил эту задачу следующим образом:
<?php
//Исходная строка
$mytext = "В поле «База данных» необходимо ввести имя базы
данных, в поле «Имя пользователя» ввести имя (логин),
которое установлено администратором для конкретного
пользователя. При последующих запусках программы поля «База
данных» и «Имя пользователя» будут заполнены. Более того,
пользователь может установить флажки на параметрах
«Сохранять пароль» и «Сохранять имя базы данных».";
//Создаем массив предложений
$text = explode(".", $mytext);
//Создаем массив из слов массива предложений
$res = array();
foreach($text as $key => $val)
{
$res[] = explode(" ", $val);
}
echo "<pre>";
print_r($text);
echo "</pre>";
echo "<pre>";
print_r($res);
echo "</pre>";
?>
|
Однако, результат мне не нравится и я не могу сообразить, в чем мои ошибки. Вопросы:
1. В массиве $text (первый дамп из моего кода) получаются четыре индекса (0,1,2,3) вместо трех ожидаемых по числу предложений. При этом 4 индекс пустой. Почему так?
2. У меня массив $text преобразуется в двумерный массив с другим именем $res, тогда как в задаче речь идет об одном и том же массиве. Как можно по-другому решить данную задачу?
Спасибо. | |
|
|
|
|
|
|
|
для: baston
(17.02.2010 в 18:09)
| | >При этом 4 индекс пустой. Почему так?
А почему? Как работает explode? | |
|
|
|
|
|
|
|
для: sim5
(17.02.2010 в 18:23)
| | В итоге получился такой код (ниже). Долго думал, искал как избавится от переноса строк. Нашел, подсказали. Даже узнал, что такое PHP_EOL.
Потом думал, как же сделать двумерный массив - тут предыдущий код товарища и помог (в цикле foreach), сам бы не додумался, точно.
<?php
//Исходная строка
$str = "текст строки с предложениями (см. выше).";
$text = array();
//Извлекаем предложения, используя разделители в виде точки и переносов строк
$tok = strtok($str, ".\r\n");
//Заносим каждое предложение в массив (и избавляемся от лишних пробелов)
while($tok)
{
$text[] = trim($tok);
$tok = strtok(".\r\n");
}
//Каждое слово каждого предожения заносим в массив
foreach($text as $key => $val)
{
$text[$key] = explode(" ", $val);
}
echo "<pre>";
print_r($text);
echo "</pre>";
?>
|
| |
|
|
|
|
|
|
|
для: baston
(18.02.2010 в 16:21)
| | Увы... Стоило добавить в предложение email и дополнительные переносы строк, как все решение пошло в разнос :(
Ладно, с переносами я придумал что делать. Избавимся от них заменой:
$str = str_replace("\r\n", "", $str);
|
А вос с точкой как концом предложения - затык... | |
|
|
|
|
|
|
|
для: baston
(19.02.2010 в 16:04)
| | Решил (подсказали алгоритм) так: ищем вхождения точек как признаки окончания предложения и заменяем их на спецсимвол. Затем уже функцией explode извлекаем наши предложения.
$badchar = array(".\"", ". ", ".\".");
$str = str_replace("\r\n", "", $str);
$str = str_replace($badchar, "ћ", $str);
$text = explode("ћ", $str);
|
| |
|
|
|
|
|
|
|
для: baston
(19.02.2010 в 17:02)
| | И кто же вам такой чудесный алгоритм подсказал? А не проще ли отрезать точку справа и explode? | |
|
|
|
|
|
|
|
для: sim5
(19.02.2010 в 17:06)
| | Вы имеете в виду так:
$text = explode(". ", trim($str));
|
В этом случае под раздачу не попадают предложения с восклицательными знаками, вопросительные. И самое плохое - последнее предложение будет с точкой, в то время как предыдущие - без точки.
Для разбора предложений с такими знаками (!?) можно воспользоваться массивом. А вот как быть с последней точкой (или другим знаком в последнем предложении)? | |
|
|
|
|
|
|
|
для: baston
(19.02.2010 в 17:27)
| | Прежде чем такое утверждать, прочтите внимательно о функции trim(). Кроме нее есть и другие. И это только один способ, возможен и другой подход. | |
|
|
|
|
|
|
|
для: sim5
(19.02.2010 в 17:32)
| | Вот елки зеленые, про трим-то я забыл совсем...
Спасибо, тестирую. | |
|
|
|
|
|
|
|
для: sim5
(19.02.2010 в 17:32)
| | Собственно говоря, получилось почти то же самое, но рабочее:
$badchar = array("! ", "? ");
$str = str_replace("\r\n", "", $str);
$str = str_replace($badchar, ". ", $str);
$text = explode(". ", rtrim($str, "."));
|
Говоря о другом подходе, вы имели в виду регулярные выражения? | |
|
|
|
|
|
|
|
для: baston
(19.02.2010 в 23:08)
| | Зада из учебника просит одно, вы же либо эту задачу иначе понимаете, либо решаете уже иную, свою.
В ней же требуется получить из строки три предложения, разбив их в последующем на массив. Заменив !? (кстати, зачем еще и с пробелом?) на точки, вы получите уже не три изначальных элемента массива.
Трудно сказать какую цель вы преследуете, но лучше решать конкретную задачу, не меняя на ходу условий ее, а находить способы ее решения, оптимизируя найденные. Коли вы учитесь, то первое, чему вы должны научиться, это среди набора стамесок уметь найти ту, которая вам необходима. А в РНР набор этих стамесок иногда с излишеством.
Не обязательно рег. выражения, есть еще масса функций работы с массивами. К рег. выражениям возможно придется прибегнуть, если, как вы сказали ранее, в строке будет e-mail, но тогда и суть задачи должна быть иной. | |
|
|
|
|
|
|
|
для: sim5
(20.02.2010 в 06:07)
| | Вы правы, я просто усложнил себе задачу - привычка такая...
Решение однозначно такое (для обычных предложений, не утяжеленных данными, которые бы привели к некорректному результату):
$text = explode(".", trim($str, "."));
foreach($text as $key => $val)
{
$text[$key] = explode(" ", trim($val));
}
echo "<pre>";
print_r($text);
echo "</pre>";
|
| |
|
|
|
|
|
|
|
для: baston
(17.02.2010 в 18:09)
| |
<?php
//Исходная строка
$mytext = "В поле «База данных» необходимо ввести имя базы
данных, в поле «Имя пользователя» ввести имя (логин),
которое установлено администратором для конкретного
пользователя.При последующих запусках программы поля «База
данных» и «Имя пользователя» будут заполнены.Более того,
пользователь может установить флажки на параметрах
«Сохранять пароль» и «Сохранять имя базы данных»";
//Создаем массив предложений
$text = explode(".", $mytext);
//Создаем массив из слов массива предложений
$res = array();
foreach($text as $key => $val)
{
$text[$key] = explode(" ", $val);
}
echo "<pre>";
print_r($text);
echo "</pre>";
?>
|
| |
|
|
|
|
|
|
|
для: t3ma
(17.02.2010 в 19:15)
| | [поправлено модератором] | |
|
|
|
|
|
|
|
для: sim5
(17.02.2010 в 19:21)
| | Честно говоря, только что приехал с работы. Прочитал коммент Sim5 и не стал пока читать следующий коммент (для своего же блага).
Еще раз перечитал описание функции explode и размышляю так: поскольку она ищет разделитель в строке (в данном случае, это точка), то обнаруживает их аж 4. Поэтому она разбивает строку на эти 4 части и в 4-ю как раз и входит "пустота" или остаток строки.
По-моему, так.
Подумаю над другим решением этой задачи.
Спасибо за помощь. | |
|
|
|
|
|
|
|
для: baston
(17.02.2010 в 19:55)
| | Точек она обнаруживает 3, потому и разбивает строку на 4 элемента.
Господин выше, пошел по пути наименьшего сопротивления - подгнал исходную строку под нужный ответ. Вы же должны подумать как решить эту проблему, данные определены задачей, и вы должны исходить из этих данных.
Вот и думайте, как решить эту проблему, а способов может быть несколько.
PS. А вы впредь в своих постах не допускайте такого текста необъятного в ширину, если обрамляете его тегом СОDE. Скроллинг по горизонтали не очень приятен, и читать такое..... | |
|
|
|
|
|
|
|
для: sim5
(17.02.2010 в 20:01)
| | если уж оставить строку как есть то первое что пришло на ум вот:
<?php
//Создаем массив предложений
$text = explode(".", $mytext);
foreach($text as $key => $val)
{
$arr = explode(" ", $val);
foreach($arr as $bb => $gg) {
if (in_array("", $arr)) {
unset ($arr[$bb]);
}
}
if (!empty($arr) && isset($text[$key])) {
$text[$key] = $arr;
} else unset ($text[$key]);
}
echo "<pre>";
print_r($text);
echo "</pre>";
?>
|
| |
|
|
|
|
|
|
|
для: sim5
(17.02.2010 в 20:01)
| | Да, 3 точки, конечно же.
По скроллингу: думал, что перенос текста будет автоматическим. Ан нет... Учту на будущее.
Спасибо. | |
|
|
|