Самый эффективный способ проверить, начинается ли $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"
Это изменилось.
Ответы
Ответ 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, но мой совет стоит.