Любая стандартная библиотека perl, чтобы проверить, содержит ли строка заданную подстроку - PullRequest
0 голосов
/ 19 сентября 2011

Учитывая запрос, я хотел бы проверить, содержит ли он заданную подстроку (может содержать более одного слова). Но я не хочу исчерпывающего поиска, потому что эта подстрока может начинать только новое слово.

Какие-нибудь стандартные библиотеки Perl для этого, чтобы я получил что-то эффективное и не нужно заново изобретать колесо?

Спасибо

Ответы [ 5 ]

2 голосов
/ 19 сентября 2011

Я бы сделал хеш с ключом, являющимся первым словом из 9000 подстрок, а значением был бы массив со всеми подстроками с этим первым словом. Если много строк содержат одно и то же первое слово, вы можете использовать первые два слова.

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

Предполагая, что сопоставление редкое, это было бы довольно эффективно. Один поиск по хешу на слово и минимальный поиск потенциальных совпадений.

Когда я пишу это, это напоминает мне о поиске ахораксика. (См. Algorithm :: AhoCorasick в CPAN.) Я никогда не использовал модуль, но алгоритм тратит много времени на построение конечного автомата из ключей поиска, поэтому поиск совпадения является суперэффективным. Я не знаю, обрабатывает ли реализация CPAN проблемы с границами слов.

2 голосов
/ 19 сентября 2011

Может быть, вы найдете встроенный index() подходящий для работы.

Это очень быстрая функция поиска подстрок (реализует алгоритм Бойера-Мура).

Просто проверьте документацию с помощью perldoc -f index.

1 голос
/ 19 сентября 2011

Встроенная функция index - это самый быстрый универсальный способ проверить, содержит ли строка подстроку.

my $find = 'abc';

my $str = '123 abc xyz';

if (index($str, $find) != -1) {
    # process matching $str here
}

Если index все еще недостаточно быстр, и вы знаете, где в строке может быть ваша подстрока, вы можете сузить ее с помощью substr, а затем использовать eq для фактического сравнения:

my $find = 'abc';

my $str = '123 abc xyz';

if (substr($str, 4, 3) eq $find) {
    # process matching $str here
}

Вы не получите быстрее, чем в Perl, не опустившись до C.

1 голос
/ 19 сентября 2011

Вы можете использовать этот подход:

# init
my $re = join"|", map quotemeta, sort @substrings;
$re = qr/\b(?:$re)/;

# usage
while (<>) {
  found($1) if /($re)/;
}

, где found - действие, которое вы хотите выполнить, если найдена подстрока.

0 голосов
/ 19 сентября 2011

Это звучит как идеальная работа для регулярных выражений :

if($string =~ m/your substring/) { 
    say "substring found"; 
} else { 
    say "nothing found"; 
}
...