Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Вопросы о преобразовании массива в двумерный (задача из книги)
 
 автор: baston   (17.02.2010 в 18:09)   письмо автору
 
 

Очень нуждаюсь в пояснении к решению очередной задачи из книги авторов сайта "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, тогда как в задаче речь идет об одном и том же массиве. Как можно по-другому решить данную задачу?

Спасибо.

  Ответить  
 
 автор: sim5   (17.02.2010 в 18:23)   письмо автору
 
   для: baston   (17.02.2010 в 18:09)
 

>При этом 4 индекс пустой. Почему так?

А почему? Как работает explode?

  Ответить  
 
 автор: baston   (18.02.2010 в 16:21)   письмо автору
 
   для: 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   (19.02.2010 в 16:04)   письмо автору
 
   для: baston   (18.02.2010 в 16:21)
 

Увы... Стоило добавить в предложение email и дополнительные переносы строк, как все решение пошло в разнос :(
Ладно, с переносами я придумал что делать. Избавимся от них заменой:
$str = str_replace("\r\n", "", $str);

А вос с точкой как концом предложения - затык...

  Ответить  
 
 автор: baston   (19.02.2010 в 17:02)   письмо автору
 
   для: baston   (19.02.2010 в 16:04)
 

Решил (подсказали алгоритм) так: ищем вхождения точек как признаки окончания предложения и заменяем их на спецсимвол. Затем уже функцией explode извлекаем наши предложения.
$badchar = array(".\"", ". ", ".\".");
$str = str_replace("\r\n", "", $str);
$str = str_replace($badchar, "ћ", $str);
$text = explode("ћ", $str);

  Ответить  
 
 автор: sim5   (19.02.2010 в 17:06)   письмо автору
 
   для: baston   (19.02.2010 в 17:02)
 

И кто же вам такой чудесный алгоритм подсказал? А не проще ли отрезать точку справа и explode?

  Ответить  
 
 автор: baston   (19.02.2010 в 17:27)   письмо автору
 
   для: sim5   (19.02.2010 в 17:06)
 

Вы имеете в виду так:
$text = explode(". ", trim($str));

В этом случае под раздачу не попадают предложения с восклицательными знаками, вопросительные. И самое плохое - последнее предложение будет с точкой, в то время как предыдущие - без точки.
Для разбора предложений с такими знаками (!?) можно воспользоваться массивом. А вот как быть с последней точкой (или другим знаком в последнем предложении)?

  Ответить  
 
 автор: sim5   (19.02.2010 в 17:32)   письмо автору
 
   для: baston   (19.02.2010 в 17:27)
 

Прежде чем такое утверждать, прочтите внимательно о функции trim(). Кроме нее есть и другие. И это только один способ, возможен и другой подход.

  Ответить  
 
 автор: baston   (19.02.2010 в 17:34)   письмо автору
 
   для: sim5   (19.02.2010 в 17:32)
 

Вот елки зеленые, про трим-то я забыл совсем...
Спасибо, тестирую.

  Ответить  
 
 автор: baston   (19.02.2010 в 23:08)   письмо автору
 
   для: sim5   (19.02.2010 в 17:32)
 

Собственно говоря, получилось почти то же самое, но рабочее:
$badchar = array("! ", "? ");
$str = str_replace("\r\n", "", $str);
$str = str_replace($badchar, ". ", $str);
$text = explode(". ", rtrim($str, "."));

Говоря о другом подходе, вы имели в виду регулярные выражения?

  Ответить  
 
 автор: sim5   (20.02.2010 в 06:07)   письмо автору
 
   для: baston   (19.02.2010 в 23:08)
 

Зада из учебника просит одно, вы же либо эту задачу иначе понимаете, либо решаете уже иную, свою.
В ней же требуется получить из строки три предложения, разбив их в последующем на массив. Заменив !? (кстати, зачем еще и с пробелом?) на точки, вы получите уже не три изначальных элемента массива.
Трудно сказать какую цель вы преследуете, но лучше решать конкретную задачу, не меняя на ходу условий ее, а находить способы ее решения, оптимизируя найденные. Коли вы учитесь, то первое, чему вы должны научиться, это среди набора стамесок уметь найти ту, которая вам необходима. А в РНР набор этих стамесок иногда с излишеством.

Не обязательно рег. выражения, есть еще масса функций работы с массивами. К рег. выражениям возможно придется прибегнуть, если, как вы сказали ранее, в строке будет e-mail, но тогда и суть задачи должна быть иной.

  Ответить  
 
 автор: baston   (24.02.2010 в 11:38)   письмо автору
 
   для: 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>";

  Ответить  
 
 автор: t3ma   (17.02.2010 в 19:15)   письмо автору
 
   для: 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>";
?> 

  Ответить  
 
 автор: sim5   (17.02.2010 в 19:21)   письмо автору
 
   для: t3ma   (17.02.2010 в 19:15)
 

[поправлено модератором]

  Ответить  
 
 автор: baston   (17.02.2010 в 19:55)   письмо автору
 
   для: sim5   (17.02.2010 в 19:21)
 

Честно говоря, только что приехал с работы. Прочитал коммент Sim5 и не стал пока читать следующий коммент (для своего же блага).
Еще раз перечитал описание функции explode и размышляю так: поскольку она ищет разделитель в строке (в данном случае, это точка), то обнаруживает их аж 4. Поэтому она разбивает строку на эти 4 части и в 4-ю как раз и входит "пустота" или остаток строки.
По-моему, так.
Подумаю над другим решением этой задачи.
Спасибо за помощь.

  Ответить  
 
 автор: sim5   (17.02.2010 в 20:01)   письмо автору
 
   для: baston   (17.02.2010 в 19:55)
 

Точек она обнаруживает 3, потому и разбивает строку на 4 элемента.
Господин выше, пошел по пути наименьшего сопротивления - подгнал исходную строку под нужный ответ. Вы же должны подумать как решить эту проблему, данные определены задачей, и вы должны исходить из этих данных.
Вот и думайте, как решить эту проблему, а способов может быть несколько.

PS. А вы впредь в своих постах не допускайте такого текста необъятного в ширину, если обрамляете его тегом СОDE. Скроллинг по горизонтали не очень приятен, и читать такое.....

  Ответить  
 
 автор: t3ma   (17.02.2010 в 20:35)   письмо автору
 
   для: 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>";
?>

  Ответить  
 
 автор: baston   (17.02.2010 в 21:15)   письмо автору
 
   для: sim5   (17.02.2010 в 20:01)
 

Да, 3 точки, конечно же.
По скроллингу: думал, что перенос текста будет автоматическим. Ан нет... Учту на будущее.
Спасибо.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования