Если у меня есть строка "Hello I went to the store today"
и у меня был массив совпадений
$perfectMatches = array("i went","store today");
Он должен соответствовать обоим. (массив может стать довольно большим, поэтому я бы предпочел сделать это в 1 preg_match)
Изменить: Получил эту работу! благодаря!
preg_match_all("/\b(" . implode($perfectMatches,"|") . ")\b/i", $string, $match1)
Мне также нужно отдельное регулярное выражение, которое трудно объяснить. Скажем, у меня есть массив
$array = array("birthday party","ice cream");//this can be very long
Можно ли получить регулярное выражение, которое будет соответствовать строке, если «день рождения» и «участник» и где угодно в строке?
Поэтому он должен соответствовать «Привет, это мой день рождения, и у меня будет вечеринка»? Но с «мороженым» также в 1 preg_match?
благодаря
Изменить: Пример …
Пользователь отправляет описание элемента, и я хочу проверить спам. Я знаю, что в большинстве сообщений со спамом есть фразы типа «личные чеки» или «горячая сделка», поэтому я хочу получить список всех этих фраз и проверить его с описанием. Если в описании есть какие-либо фразы в моем списке, он будет помечен как спам. Этот сценарий применим к первому регулярному выражению, которое я хочу.
Второе регулярное выражение было бы, если бы я знал, что в некоторых сообщениях со спамом есть слова «потерять» «вес» «быстро» где-то там, не обязательно в любом порядке, но эти 3 слова приведены в описании. Поэтому, если я получу список этих фраз «быстро похудеть», «требуется кредитная карта» и проверьте ее с описанием, я могу отметить ее как спам
Похоже, что часть 1 вашей проблемы уже решена, поэтому этот ответ сосредоточен только на части 2. Как я понимаю, вы пытаетесь определить, содержит ли данное входное сообщение весь список слов в любом порядке.
Это можно сделать с помощью регулярного выражения и одного preg_match
для каждого сообщения, но оно очень неэффективно, если у вас есть большой список слов. Если N – количество слов, которые вы ищете, а M – длина сообщения, тогда алгоритм должен быть O (N * M). Если вы заметили, есть два .*
Выражения в регулярном выражении для каждого ключевого слова. С утверждениями lookahead, движок регулярных выражений должен проходить один раз для каждого ключевого слова. Вот пример кода:
<?php // sample messages $msg1 = "Lose all the weight all the weight you want. It's fast and easy!"; $msg2 = 'Are you over weight? lose the pounds fast!'; $msg3 = 'Lose weight slowly by working really hard!'; // spam defining keywords (all required, but any order). $keywords = array('lose', 'weight', 'fast'); //build the regex pattern using the array of keywords $patt = '/(?=.*\b'. implode($keywords, '\b.*)(?=.*\b') . '\b.*)/is'; echo "The pattern is: '" .$patt. "'\n"; echo 'msg1 '. (preg_match($patt, $msg1) ? 'is' : 'is not') ." spam\n"; echo 'msg2 '. (preg_match($patt, $msg2) ? 'is' : 'is not') ." spam\n"; echo 'msg3 '. (preg_match($patt, $msg3) ? 'is' : 'is not') ." spam\n"; ?>
Выход:
The pattern is: '/(?=.*\blose\b.*)(?=.*\bweight\b.*)(?=.*\bfast\b.*)/is' msg1 is spam msg2 is spam msg3 is not spam
Это второе решение кажется более сложным, потому что есть больше кода, но регулярное выражение намного проще. У него нет никаких ожиданий и нет. Функция preg_match
вызывается в цикле while, но это не очень важно. Каждое сообщение перемещается только один раз, а сложность должна быть O (M). Это также можно сделать с помощью одной функции preg_match_all
, но тогда вам нужно будет выполнить array_search
чтобы получить окончательный счет.
<?php // sample messages $msg1 = "Lose all the weight all the weight you want. It's fast and easy!"; $msg2 = 'Are you over weight? lose the pounds fast!'; $msg3 = 'Lose weight slowly by working really hard!'; // spam defining keywords (all required, but any order). $keywords = array('lose', 'weight', 'fast'); //build the regex pattern using the array of keywords $patt = '/(\b'. implode($keywords,'\b|\b') .'\b)/is'; echo "The pattern is: '" .$patt. "'\n"; echo 'msg1 '. (matchall($patt, $msg1, $keywords) ? 'is' : 'is not') ." spam\n"; echo 'msg2 '. (matchall($patt, $msg2, $keywords) ? 'is' : 'is not') ." spam\n"; echo 'msg3 '. (matchall($patt, $msg3, $keywords) ? 'is' : 'is not') ." spam\n"; function matchall($patt, $msg, $keywords) { $offset = 0; $matches = array(); $index = array_fill_keys($keywords, 0); while( preg_match($patt, $msg, &$matches, PREG_OFFSET_CAPTURE, $offset) ) { $offset = $matches[1][1] + strlen($matches[1][0]); $index[strtolower($matches[1][0])] += 1; } return min($index); } ?>
Выход:
The pattern is: '/(\blose\b|\bweight\b|\bfast\b)/is' msg1 is spam msg2 is spam msg3 is not spam