Как искать массив строк в другой строке в PHP? - PullRequest
5 голосов
/ 03 июня 2011

Во-первых, я хочу сообщить, что мне нужна обратная функция PHP in_array.

Мне нужно найти все элементы массива в строке, если какой-либо из них найден, в противном случае функция вернет truereturn false.

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

Любые предложения приветствуются.

Пример данных:

$string = 'Alice goes to school every day';

$searchWords = array('basket','school','tree');

возвращает true

$string = 'Alice goes to school every day';

$searchWords = array('basket','cat','tree');

возвращает false

Ответы [ 7 ]

10 голосов
/ 03 июня 2011

Вы должны попробовать с preg_match:

if (preg_match('/' . implode('|', $searchWords) . '/', $string)) return true;

После некоторых комментариев здесь правильно избежавшее решение:

function contains($string, Array $search, $caseInsensitive = false) {
    $exp = '/'
        . implode('|', array_map('preg_quote', $search))
        . ($caseInsensitive ? '/i' : '/');
    return preg_match($exp, $string) ? true : false;
}
3 голосов
/ 03 июня 2011

Как на примере malko, но с правильным экранированием значений.

function contains( $string, array $search ) {
    return 0 !== preg_match( 
        '/' . implode( '|', preg_quote( $search, '/' ) ) . '/', 
        $string 
    );
}
3 голосов
/ 03 июня 2011
function searchWords($string,$words)
{
    foreach($words as $word)
    {
        if(stristr($string," " . $word . " ")) //spaces either side to force a word
        {
            return true;
        }
    }
    return false;
}

Использование:

$string = 'Alice goes to school every day';
$searchWords = array('basket','cat','tree');

if(searchWords($string,$searchWords))
{
     //matches
}

Также обратите внимание, что функция stristr используется для того, чтобы не чувствителен к регистру

3 голосов
/ 03 июня 2011

Если строка может быть взорвана с использованием пробела, будет работать следующее:

var_dump(array_intersect(explode(' ', $str), $searchWords) != null);

ВЫХОД: для 2 предоставленных вами примеров:

bool(true)
bool(false)

Обновление:

Если строка не может быть разнесена с помощью пробела, используйте такой код для разделения строки на любой конец слова :

var_dump(array_intersect(preg_split('~\b~', $str), $searchWords) != null);
0 голосов
/ 14 ноября 2013

Ниже ссылка поможет вам: просто нужно настроить так, как вам нужно.

Проверьте, существует ли элемент массива в строке

customized:

function result_arrayInString($prdterms,208){
  if(arrayInString($prdterms,208)){
      return true;
  }else{
     return false;
  }
}

Это может быть полезно для вас.

0 голосов
/ 03 июня 2011

Всегда спорят о том, что быстрее, поэтому я решил запустить несколько тестов, используя разные методы.

Выполнение тестов:

  1. strpos
  2. preg_match с циклом foreach
  3. preg_match с регулярным выражением или
  4. индексированный поиск со строкой для взрыва
  5. индексированный поиск в виде массива (строка уже взорвана)

Два набора тестов, где выполняются.Один на большом текстовом документе (114 350 слов) и один на небольшом текстовом документе (120 слов).В каждом наборе все тесты были проведены 100 раз, а затем было взято среднее значение.Тесты не игнорировали случай, который сделал бы их все быстрее.Тест, по которому был выполнен поиск по индексу, был предварительно проиндексирован.Я сам написал код для индексации, и я уверен, что он был менее эффективен, но индексация для большого файла заняла 17,92 секунды, а для маленького файла - 0,001 секунды.НЕ найдены в документе), юридически (найдены в документе) и цели (НЕ найдены в документе).

Результаты в секундах для завершения одного теста, отсортированные по скорости:

Большой файл:

  1. 0.0000455808639526 (индекс без разнесения)
  2. 0.0009979915618897 (preg_match с использованием регулярного выражения или)
  3. 0.0011657214164734 (strpos)
  4. 0,0023632574081421 (preg_match с использованием цикла foreach)
  5. 0.0051533532142639 (индекс с разнесением)

Маленький файл

  1. 0.000003724098205566 (strpos)
  2. 0,000005958080291748 (preg_match с использованием регулярных выражений или)
  3. 0,000012607574462891 (preg_match с использованием цикла foreach)
  4. 0.000021204948425293 (индекс без разнесения)
  5. 0,000060625076293945 (индекс с разнесением)

Обратите внимание, что strpos быстрее, чем preg_match (с использованием регулярных выражений или), для небольших файлов, но медленнее для больших файлов.Конечно, на это будут влиять и другие факторы, например количество поисковых терминов.

Используемые алгоритмы:

//strpos
$str = file_get_contents('text.txt');
$t = microtime(true);
foreach ($search as $word) if (strpos($str, $word)) break;
$strpos += microtime(true) - $t;

//preg_match
$str = file_get_contents('text.txt');
$t = microtime(true);
foreach ($search as $word) if (preg_match('/' . preg_quote($word) . '/', $str)) break;
$pregmatch += microtime(true) - $t;

//preg_match (regex or)
$str = file_get_contents('text.txt');
$orstr = preg_quote(implode('|', $search));
$t = microtime(true);
if preg_match('/' . $orstr . '/', $str) {};
$pregmatchor += microtime(true) - $t;

//index with explode
$str = file_get_contents('textindex.txt');
$t = microtime(true);
$ar = explode(" ", $str);
foreach ($search as $word) {
    $start = 0; 
    $end = count($ar);
    do {
        $diff = $end - $start;
        $pos = floor($diff / 2) + $start;
        $temp = $ar[$pos];
        if ($word < $temp) {
            $end = $pos;
        } elseif ($word > $temp) {
            $start = $pos + 1;
        } elseif ($temp == $word) {
            $found = 'true';
            break;
        }
    } while ($diff > 0);
}
$indexwith += microtime(true) - $t;

//index without explode (already in array)
$str = file_get_contents('textindex.txt');
$found = 'false';
$ar = explode(" ", $str);
$t = microtime(true);
foreach ($search as $word) {
    $start = 0; 
    $end = count($ar);
    do {
        $diff = $end - $start;
        $pos = floor($diff / 2) + $start;
        $temp = $ar[$pos];
        if ($word < $temp) {
            $end = $pos;
        } elseif ($word > $temp) {
            $start = $pos + 1;
        } elseif ($temp == $word) {
            $found = 'true';
            break;
        }
    } while ($diff > 0);
}
$indexwithout += microtime(true) - $t;
0 голосов
/ 03 июня 2011

попробуйте это:

$string = 'Alice goes to school every day';
$words = split(" ", $string); 
$searchWords = array('basket','school','tree');

for($x = 0,$l = count($words); $x < $l;) {
        if(in_array($words[$x++], $searchWords)) {
                //....
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...