Подтвердить что ты не робот

Самый эффективный способ проверить, начинается ли $string с $needle в perl

Учитывая две строковые переменные $string и $needle в perl, какой наиболее эффективный способ проверить, начинается ли $string с $needle.

  • $string =~ /^\Q$needle\E/ - это самое близкое совпадение, которое я мог бы думать о том, что делает то, что требуется, но является наименее эффективным (безусловно) решением, которое я пробовал.
  • index($string, $needle) == 0 работает и относительно эффективен для некоторых значений $string и $needle, но бесполезно ищет иглу в других позициях (если не найден в начале).
  • substr($string, 0, length($needle)) eq $needle должен быть довольно простым и эффективным, но в большинстве моих тестов не более эффективен, чем предыдущий.

Есть ли канонический способ сделать это в perl, о котором я не мог бы знать или каким-либо образом оптимизировать любое из вышеперечисленных решений?

(в моем конкретном случае использования $string и $needle в каждом прогоне будут отличаться друг от друга, поэтому предварительная компиляция регулярного выражения не является вариантом).


Пример того, как измерять производительность данного решения (здесь из POSIX sh):

string='somewhat not so longish string' needle='somew'
time perl -e '
  ($n,$string,$needle) = @ARGV;
  for ($i=0;$i<$n;$i++) {

    index($string, $needle) == 0

  }' 10000000 "$string" "$needle"

С этими значениями index() работает лучше, чем substr()+eq с этой системой с perl 5.14.2, но с:

string="aaaaabaaaaabaaaaabaaaaabaaaaabaaaaab" needle="aaaaaa"

Это изменилось.

4b9b3361

Ответ 1

Насколько это важно, действительно? Я сделал ряд тестов, а метод index усреднил 0,68 микросекунды на итерацию; метод регулярного выражения 1.14 мкс; метод substr 0,16 мкс. Даже самые худшие сценарии (2250- char, равные), index заняли 2,4 мкс, регулярное выражение заняло 5,7 мкс, а substr заняло 0,5 мкс.

Мой совет - написать библиотечную процедуру:

sub begins_with
{
    return substr($_[0], 0, length($_[1])) eq $_[1];
}

и сосредоточьте свои усилия на оптимизации в другом месте.

ОБНОВЛЕНИЕ. Основываясь на критике моего сценария "худшего случая", описанного выше, я запускал новый набор тестов с произвольно созданной строкой в ​​20 000 < char, сравнивая ее с собой и с строкой, которая отличалась только последний байт.

Для таких длинных строк решение регулярных выражений было самым худшим (20 000 символов - ад): 105 мкс для успеха в матче, 100 мкс для неудачи матча.

Решения index и substr были довольно быстрыми. index составлял 11,83 мкс /11,86 мкс для успеха/неудачи, а substr составлял 4,09 мкс /4,15 мкс. Перемещение кода в отдельную функцию добавлено около 0.222 ± 0.05μs.

Код теста доступен по адресу: http://codepaste.net/2k1y8e

Я не знаю характеристик данных @Stephane, но мой совет стоит.