Разделение, подсчет и форматирование многобайтовых символов в PHP - PullRequest
1 голос
/ 28 апреля 2020

Я создаю экспериментальное приложение PHP, которое обрабатывает стихи на кириллице c UTF-8 символов . Я хочу добиться следующего:

  • Подсчитать вхождения каждого персонажа и общее количество для таких категорий, как «все согласные». Это могут быть специальные символы и знаки препинания, если я могу скрыть некоторые из них в выводе. Я работаю на UTF-8, поэтому могу использовать только многобайтовые функции. Использование count_chars () не возможно: (
  • Сохранение разрывов строк и заглавных букв. Я сохраняю несколько копий исходного текста с различным форматированием. Они могут выглядеть избыточными, но я хочу сохранить как можно больше информации.
  • Изменение HTML форматирования определенных символов на основе условия, например, придание гласным и согласным различного цвета фона или выделение каждого вхождения выбранного символа. Насколько я понимаю, сначала мне нужно разделить строку в строки (чтобы сохранить разрывы), затем превратить каждый из них в массив из 1-символьных кусков. Для вывода я бы соединил строки () обратно. К сожалению, я не смог найти никаких идей о том, как применить HTML для массива значений, чтобы решить такую ​​проблему, как моя.

Что я пробовал

Помимо того, что я не знал, как сделать что-то, я столкнулся с некоторыми незначительными проблемами. Я делаю сейчас.

Я собираю стихотворение с помощью метода post. Поэма на английском языке sh для иллюстрации. только с

Пример текста:

We shall not cease from exploration 
And the end of all our exploring
Will be to arrive where we started
And know the place for the first time.

Я пронумеровал шаги, чтобы упростить комментирование.


1. Получение значения с тегами и без них

Вот как это выглядит в htmlentities() после отправки через textarea:

$string = "We shall not cease from exploration<br /> And the end of all our exploring<br /> Will be to arrive where we started<br /> And know the place for the first time."

Как вывести разрывы строк:

$poem = nl2br($string);

Вот копия без тегов:

$droptags = strip_tags($poem);

2. Подсчет символов

Это моя рудиментарная попытка count_chars() без подсчета l oop (s):

$poem2array = preg_split('//u', $droptags, null, PREG_SPLIT_NO_EMPTY);
$unique_characters = array_unique($poem2array);

Вывод следующий:

(
[0] => W
[1] => e
[2] => 
...
)

3. Разделение строк на массивы

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

$lines = preg_split('<br />', $showtags);

Моя проблема в том, что массив выглядит так:

(
[0] => We shall not cease from exploration<
[1] => >
And the end of all our exploring<
[2] => >
Will be to arrive where we started<
[3] => >
And know the place for the first time.
)

Моя попытка разделения текст во вложенные массивы. Я знаю, что он сломан, потому что я могу получить только последнюю строку.

foreach($lines as $line) {
      $line = preg_split('//u', $line, null, PREG_SPLIT_NO_EMPTY);
    }

4. HTML стайлинг

Что касается HTML стилевого оформления массивов, я понятия не имею. Мои эталонные массивы будут выглядеть так:

$vowels = array("a", "e", "i");
$consonants = array("b", "c", "d");

$fontcolor = array("vowels" => "blue",
                "consonants" => "orange");

Ответы [ 2 ]

1 голос
/ 02 мая 2020

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

Чтобы разбить строку на массив символов, вы должны использовать mb_str_split(). Если вы застряли с PHP <= 7,3, то вы должны использовать <code>preg_split('//u', $line, null, PREG_SPLIT_NO_EMPTY);.

. Вы можете использовать array_count_values(), чтобы уменьшить массив до количества буквенных частот. Тогда это просто вопрос подсчета гласных и согласных по отдельности.

Чтобы правильно обрабатывать многобайтовые строки, вы должны использовать расширение mbstring . Например, mb_strtolower - это многобайтовая версия strtolower(), а mb_str_split() - это многобайтовая версия str_split()

<?php

$poem = <<<'POEM'
We shall not cease from exploration 
And the end of all our exploring
Will be to arrive where we started
And know the place for the first time.
POEM;

$vowels = array("a", "e", "i", "o", "u");
$consonants = array_diff(range('a', 'z'), $vowels); // not necessary to diff because of elseif. Just for demonstration

$letterFrequencyInsesitive = array_count_values(mb_str_split(mb_strtolower($poem)));
$noVowels = 0;
$noConsonants = 0;
foreach ($letterFrequencyInsesitive as $letter => $freq) {
    if (in_array($letter, $vowels, true)) {
        $noVowels += $freq;
    } elseif (in_array($letter, $consonants, true)) {
        $noConsonants += $freq;
    }
}

echo 'Number of vowels: '.$noVowels.PHP_EOL;
echo 'Number of consonants: '.$noConsonants;

. отформатируйте каждую букву отдельно, тогда, вероятно, проще всего заключить каждую букву в тег <span> и применить класс.

$formattedOutput = '';
$fontcolor = array("vowels" => "blue",
    "consonants" => "orange");

foreach (mb_str_split($poem) as $char) {
    $lowercase = mb_strtolower($char);
    if (in_array($lowercase, $vowels, true)) {
        $formattedOutput .= '<span class="'.$fontcolor['vowels'].'">'.$char.'</span>';
    } elseif (in_array($lowercase, $consonants, true)) {
        $formattedOutput .= '<span class="'.$fontcolor['consonants'].'">'.$char.'</span>';
    } else {
        $formattedOutput .= $char;
    }
}

echo nl2br($formattedOutput);
0 голосов
/ 28 апреля 2020

Подсчет символов

for ($i=0;$i<=strlen($droptags);$i++) 
$count[$droptags[$i]]++;

Разделение строк на массивы

В этом случае мне пришлось сделать хитрость. В этом случае мне пришлось изменить маркер с
на другой маркер; в противном случае> всегда будет отображаться

$showtags = "We shall not cease from exploration<br /> And the end of all our exploring<br /> Will be to arrive where we started<br /> And know the place for the first time.";
$showtags = str_replace(";",",",$showtags);
$showtags = str_replace("<br />",";",$showtags);
$lines = preg_split('/;/', $showtags);
foreach($lines as $line) {
    echo "lines= $line<BR>";
}

В вашем коде я предлагаю изменить имя переменной, в противном случае он будет смешиваться с переменной $ line, используемой в l oop

foreach($lines as $line) {
  $lineOut = preg_split('//u', $line, null, PREG_SPLIT_NO_EMPTY);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...