2017-02-17 18 views
0

Функция, которую я использую, должна обнаруживать первый экземпляр символа, а если символ повторяется, восстановите повторяющуюся подстроку. Например:Лучший способ восстановления первого экземпляра возможно повторяющегося символа в строке без использования функций preg_ *

$x = 'fhdfhbc::::dcdcdcuttr482rdvcjv:ducvdk:::chjvdbj'; // ---> function should extract :::: 

Я не хочу использовать какие-либо из preg_* функций, как избежать их, когда это возможно (потому что эти функции медленно). Мое решение в настоящее время это:

$char = ":"; // this would be set as necessary 

$char_substring = str_repeat($char, strspn(strstr($x, $char), $char)); // yields ---> :::: 

Примечания Вы не можете использовать strrpos здесь, потому что может быть (в данном случае) колоны на другом конце строки. Вы можете использовать explode, а затем запустить for или foreach петлю, конкатенации на стеклотару, или некоторые вариации этого:

$explode = explode($char, $x); 
$substring = $char; // explode array should have 1 less empty member than the repeated character, so need to start with char count of 1 
$emptyEncountered = false; 
for($i = 0, $count = count($explode); $i < $count; $i++) { 
    if ($explode[$i]) { 
     if ($emptyEncountered) break; 
    } else { 
     $emptyEncountered = true; 
     $substring .= $char; 
    } 
} 

echo $substring; // ---> :::: 

Есть ли лучший способ, чем использование preg_ *, а для/каждого цикла, или str_repeat (strspn (strstr()))?

ответ

2

Правильная реализация preg_* будет превосходить подход ваших рук вниз не только во времени, но и с точки зрения потребления памяти и необходимых распределений.

только реализация, я думаю, что эффективно, и который прилипает к вашим ограничениям, будет while петля:

$substring = ''; 

$i = strpos($haystack, $needle); 
do { 
    $substring .= $needle; 
    ++$i; 
} 
while (isset($haystack{$i}) && $haystack{$i} === $needle); 

return $substring; 

Однако, у вас уже есть наиболее эффективное осуществление самостоятельно:

return str_repeat($needle, strspn(strstr($haystack, $needle), $needle)); 

Он также прекрасно функционирует в природе.

В ваших реализациях отсутствует обработка ошибок, поэтому моя реализация while. Добавление, безусловно, требуется, на мой взгляд, но я игнорирую его, потому что вы это делаете.


Результаты на моей машине i7 с Win 10 PHP TS x64 7.1:

$ bench 10000 
0.0040609836578369 # str_repeat 
0.0044500827789307 # preg_match 
0.0046060085296631 # while 
0.0050818920135498 # for 
0.0052239894866943 # preg_match + preg_quote 
0.0079050064086914 # explode 

#!/usr/bin/env php 
<?php 

function bench(callable $cb): void { 
    global $argv; 

    $limit = 1000; 
    if (isset($argv[1]) && is_numeric($argv[1])) { 
     $limit = (int) $argv[1]; 
    } 
    elseif (isset($_ENV['LOOP']) && is_numeric($_ENV['LOOP'])) { 
     $limit = (int) $_ENV['LOOP']; 
    } 

    gc_collect_cycles(); 
    gc_disable(); 
    $start = microtime(true); 
    for ($i = 0; $i < $limit; ++$i) { 
     $cb(); 
    } 
    $end = microtime(true); 
    gc_enable(); 
    gc_collect_cycles(); 

    echo $end - $start, "\n"; 
} 

$haystack = 'fhdfhbc::::dcdcdcuttr482rdvcjv:ducvdk:::chjvdbj'; 
$needle = ':'; 

bench(function() use ($haystack, $needle) { 
    return str_repeat($needle, strspn(strstr($haystack, $needle), $needle)); 
}); 

bench(function() use ($haystack, $needle) { 
    preg_match("/{$needle}{2,}/", $haystack, $matches); 

    return $matches[0] ?? ''; 
}); 

bench(function() use ($haystack, $needle) { 
    $substring = ''; 
    $i   = strpos($haystack, $needle); 

    do { 
     $substring .= $needle; 
     ++$i; 
    } 
    while (isset($haystack{$i}) && $haystack{$i} === $needle); 

    return $substring; 
}); 

bench(function() use ($haystack, $needle) { 
    $substring = ''; 

    for ($i = strpos($haystack, $needle); isset($haystack{$i}) && $haystack{$i} === $needle; ++$i) { 
     $substring .= $needle; 
    } 

    return $substring; 
}); 

bench(function() use ($haystack, $needle) { 
    $needle = preg_quote($needle, '/'); 

    preg_match("/{$needle}{2,}/", $haystack, $matches); 

    return $matches[0] ?? ''; 
}); 

bench(function() use ($haystack, $needle) { 
    $explode = explode($needle, $haystack); 
    $substring = $needle; 
    $empty  = false; 

    for ($i = 0, $count = count($explode); $i < $count; $i++) { 
     if ($explode[$i]) { 
      if ($empty) { 
       break; 
      } 
     } 
     else { 
      $empty  = true; 
      $substring .= $needle; 
     } 
    } 

    return $substring; 
}); 

 Смежные вопросы

  • Нет связанных вопросов^_^