regex — исправление неработающих заголовков с пробелами между буквами в переполнении стека

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

Вот несколько примеров названий (знак минус обозначает пробел).

"H-E-L-L-O--W-O-R-L-D"
"H--E--L--L--O----W--O--R--L--D"
"H--E--L-L--O---W--O--R--L--D----A-N-D----G-O-O--D-B--Y-E"
"Y--O--U----A--R--E----W-O-N--D-E-R-F-U--L"

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

Какие-либо решения?


РЕДАКТИРОВАТЬ: Это решение, которое я выбрал в конце, который основан на среднем,

function filterSpacesBetweenLetters($str)
{
if (preg_match_all('/ +/', $str, $matches)) {
$lengthValues = array_map('strlen', $matches[0]);

$countValues = array_count_values($lengthValues);

$average = array_sum(array_keys($countValues)) / count($countValues);

$minLength = ceil($average);

$words = preg_split('/ {' . $minLength . ',}/', $str);

$words = array_map(function ($str) {
return str_replace(' ', '', $str);
}, $words);

return implode(' ', $words);
}

return $str;
}

0

Решение

Все, что я могу придумать, — это иметь механизм, который ищет наибольшее количество символов тире в последовательности и применять правила замены в наборах 3/4 или 1/2.

$text = <<<END
H-E-L-L-O--W-O-R-L-D
H--E--L--L--O----W--O--R--L--D
H--E--L-L--O---W--O--R--L--D----A-N-D----G-O-O--D-B--Y-E
Y--O--U----A--R--E----W-O-N--D-E-R-F-U--L
END;

$lines = explode( PHP_EOL, $text );

foreach( $lines as $key => $line )
{
if( preg_match_all( '/-*/', $line, $matches ) !== false )
{
$counts = array_map( 'strlen', $matches[0] );
if( max( $counts ) >= 3 )
{
$line = preg_replace('/-{3,4}/',' ', $line );
$line = preg_replace('/-{1,2}/','', $line );
}
else
{
$line = replace( '--', ' ', $line );
$line = replace( '-', '', $line );
}
}
echo $line . PHP_EOL;
}

Все, что находится за пределами этих правил, не будет соответствовать, двойные пробелы полностью испортят это.

Печать

HELLO WORLD
HELLO WORLD
HELLO WORLD AND GOODBYE
YOU ARE WONDERFUL
2

Другие решения

Я хотел добавить подход без зацикливания (но использует какой-то preg, которого я тоже пытался избежать).

Найдите самое длинное непрерывное число пробелов. Токенизируйте строку, разбив ее на «самое большое пространство», чтобы получить массив «слов». Уберите пробел из каждого слова. Положите его обратно вместе.

<?php

function stripSpace($str) {
return str_replace(' ', '', $str);
}

$test = 'H E L L O  W O R L D';
//$test = 'H  E  L  L  O    W  O  R  L  D    A  G  A  I  N';

preg_match_all('#(\s)\1+#', $test, $m);
usort($m[0], function($a, $b) {
return (strlen($a) < strlen($b)) ? 1 : -1;
});
$m = strlen($m[0][0]);

$parts = explode(str_repeat(chr(32), $m), $test);

$parts = array_map('stripSpace', $parts);

echo implode($parts, chr(32));
0