PHP需要计算字符串中序列中相同字符的数量

时间:2014-10-12 10:23:41

标签: php

我使用php在rtf格式文件中合并文本服务器端。 我的字段由文件不同部分中的一系列波浪号标识。 每个序列的长度不同。 为了使用substr_replace用合并材料替换字段,我需要计算渐变序列的长度。 我可以使用以下方法找到第一个没有问题的代字号:

$firsttilde=strpos($filedata,'~',$currentposinfile);

其中(在此代码中)$filedata是包含文件内容的字符串,$currentposinfile是我搜索的起点。 我的问题是我找不到一个可以计算序列中相同字符数的函数。

从我看到的$filedata的第一个代号看起来像这样(换句话说是一系列代字号):

  

' ~~~~~~~~~~'

我已经尝试strrpos找到最后一个代字号,但这是在$filedata的后面部分找到包含波浪号的字段。 我想要做的就是从字符串中我知道的位置计算波浪号的数量,但我找不到任何函数来执行此操作。 但必须有一个。

4 个答案:

答案 0 :(得分:0)

您可以将preg_match_allPREG_OFFSET_CAPTURE标志结合使用。这将保存在匹配变量中找到字符串的偏移量,允许您同时找到字符串及其偏移量。

$matches = Array();
preg_match_all( '/~+/', $input, $matches, PREG_OFFSET_CAPTURE);

foreach( $matches[0] as $k => $v ) {
  $length = strlen( $v[0] );
  echo "Found a string \"{$v[0]}\" beginning at {$v[1]} with length {$length}<br>";
}

对于下面的示例文本

$input = <<<TEXT
this is
~~~~~~~~

quite something
~~~~
TEXT;
输出将是:

Found a string "~~~~~~~~" beginning at 8 with length 8
Found a string "~~~~" beginning at 34 with length 4

答案 1 :(得分:0)

这使用for迭代来检查文本中的字符。 它是preg_match()解决方案的替代方案,它更紧凑。

<?php

$text = <<<'TEXT'
abc
~~~
def
~~~~~~
123
~~~~~~~~~~
TEXT;

//$currentposinfile = 0;
//$firsttilde = strpos($text,'~',$currentposinfile);
//$text = substr($text, $firsttilde);

$sequenceStarted = false;
$sequenceLength = 0;

$textLength = strlen($text);

for ($i = 0; $i <= $textLength; $i++) {
    $char = $text[$i]; 

    //echo 'Char ' . $char . '  at ' . $i . PHP_EOL;

    if($char === '~') {

        // found start of a sequence
        if($sequenceStarted === false) {
           $sequenceLength++;      
           $sequenceStarted = true;      
           $sequenceStartPosition = $i;
        } 

        // it's a char in sequence               
        continue;
    }

    // found first char out of sequence
    if($char !== '~' && $sequenceStarted === true) {
         $sequenceStarted = false;
         $sequenceEndPostion = $i - 1;
         $sequenceLength = $i - $sequenceStartPosition;

         echo 'Found a sequence of length: ' .  $sequenceLength . ' starting at '.$sequenceStartPosition.' ending at ' . $sequenceEndPostion . '.' . PHP_EOL;

         #break;

         $sequenceLength = 0; $sequenceEndPostion = 0;
    }
}

结果:

Found a sequence of length: 3 starting at 5 ending at 7.
Found a sequence of length: 6 starting at 15 ending at 20.
Found a sequence of length: 10 starting at 28 ending at 37.

如果您已经拥有序列块,则可以使用count_chars()

<?php

$text = 'ABC~~~123';

$data = count_chars($text, 1);

echo 'The string "'. $text .'" contains the char "~" '. $data[126] . ' times.';

$ data [126] =使用ASCII码126表示〜

结果:字符串“ABC ~~~ 123”包含char“〜”3次。

演示:https://eval.in/204882

答案 2 :(得分:0)

以下函数将遍历字符串并返回匹配数组:

function findSequences($str)
{
    $ret = array();
    $len = strlen($str);
    $count = 0;

    for($i = 0; $i <= $len; $i ++)
    {
        $char = @$str[$i] ?: null;

        if($char == '~')
        {
            $count ++;
        }
        elseif($count > 0)
        {
            // Found end of sequence
            $ret[] = array(
                'start' => $i - $count,
                'end' => $i - 1,
                'len' => $count
            );

            $count = 0;
        }
    }

    return $ret;
}

使用示例:

print_r(findSequences('~ABC~~~123~~'));

将输出一个包含找到的匹配项详细信息的数组:

Array
(
    [0] => Array
        (
            [start] => 0
            [end] => 0
            [len] => 1
        )

    [1] => Array
        (
            [start] => 4
            [end] => 6
            [len] => 3
        )

    [2] => Array
        (
            [start] => 10
            [end] => 11
            [len] => 2
        )

)

答案 3 :(得分:0)

感谢大家的回答 他们鼓励我尝试更难找到一个简单的解决方案。

我想出了这个: -

$lasttilde=$firsttilde;
while ($filedata[$lasttilde]=='~') { $lasttilde++; }

然后$filedata特定部分的代字号数量是$lasttilde$firsttilde之间的差异