在PHP中用字母之间的空格更正损坏的标题

时间:2019-02-04 23:09:20

标签: php regex text data-cleaning

我有一堆破碎的标题,其中每个字母总是用一个或多个空格隔开。这些标题中的单词之间的空格数量大于每个字母的数量,但是空格数量会有所不同。

以下是标题的一些示例(减号表示空格)。

"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;
}

2 个答案:

答案 0 :(得分:2)

我能想到的就是拥有一种机制,该机制可以按顺序查找最大数量的破折号并在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

答案 1 :(得分:0)

我想添加一种没有循环的方法(但确实使用了我也想避免的预浸料)。

查找最长连续的空格数。标记化字符串,在“最大空间”上分割,以获得“单词”数组。删除每个单词的空格。放回去。

<?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));