2015-12-15 4 views
1

Я ищу способ вернуть начальную позицию и сопоставленный шаблон из строки (возможно) непоследовательных шаблонов соответствия любой комбинации $search в $pattern от $length.Найти непересекающиеся комбинации слов в строке из массива слов с помощью PHP

В моем примере, ищем номера телефонов, где цифры - это слова.

$subject = "hello my name is inigo montoya you killed my father please call me at eight zero zero five five five one to three four prepare to die" 

$search = array("zero", "one", "two", "to", "too" "three", "four", "five", "six", "seven", "eight", "nine") 

$length = 10; 

$result = jedi_find_trick($subject,$search,$length); 

установлен ли $result в массив:

$result[0]["start"] = 70 
$result[0]["match"] = "eight zero zero five five five one to three four" 
$result[1] ... 

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


на основе @ Chris85-х внушения, это, кажется отличной отправной точкой:

$subject = 'hello my name is inigo montoya you killed my father please call me at eight zero zero five five five one to three four or too oh five seven seven seven five one one one prepare to die'; 
$search = array('zero','oh','one','two','too','to','three','four','five','six','seven','eight','nine','hundred','thousand'); 
$replace = array('0','0','1','2','2','2','3','4','5','6','7','8','9','00','000'); 
$length = 10; 

$result = jedi_find_trick($subject,$search,$replace,10); 

$result = jedi_find_trick($subject,$search,$replace,$length); 

print_r($result); 

function jedi_find_trick($subject,$search,$replace,$length) { 

    preg_match_all('/(\h*(' . implode('|', $search) . ')\h*){10}/', $subject, $numbers); 

    foreach($numbers[0] as $match) { 

     $number = str_replace($search,$replace,$match); 
     $number = str_replace(' ', '', $number); 
     $number = ' ' . $number . ' '; 
     $subject = str_replace($match,$number,$subject); 

    } 

    return $subject; 
} 

Возвращает:

hello my name is inigo montoya you killed my father please call me at 8005551234 or 2057775111 prepare to die 

С str_replace() "слишком" должны были бы быть в $search перед тем «to» или вы получите «2o». Некоторая граница слов, посвященная preg_replace(), должна очистить ее.

+1

Возможно, что-то вроде этого, https://eval.in/485791? – chris85

+2

Что вы подразумеваете под «не последовательными»? –

+0

Значения '$ search' могут быть не в том же порядке в' $ subject', как в массиве. –

ответ

1

Что-то вроде этого:

$subject = 'hello my name is inigo montoya you killed my father please call me ' 
     . 'at eight zero zero five five five one to three four prepare to die'; 

$search = ['zero', 'one', 'two', 'to', 'too', 'three', 'four', 'five', 'six', 
      'seven', 'eight', 'nine']; 

$length = 10; 

function jedi_find_trick($search, $subject, $length, $sep = ' ', $septype = 0) { 
    // quote special characters in the search list 
    $search = array_map(function ($i) { return preg_quote($i, '~'); }, $search); 
    // quote the separator when it is a literal string 
    if ($septype === 0) $sep = preg_quote($sep, '~'); 

    // build the pattern 
    $altern = '(?:' . implode('|', $search) . ')'; 

    $format = '~(?:%1$s|\A)(%2$s' 
      . ($length<2 ? '': '(?:%1$s%2$s){%3$d}') 
      . ')(?=%1$s|\z)~'; 

    $pattern = sprintf($format, $sep, $altern, $length - 1); 

    if (preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE)) 
     return $matches[1]; 

    // return an empty array if there is no match 
    return []; 
} 

print_r(jedi_find_trick($search, $subject, $length)); 
print_r(jedi_find_trick($search, $subject, 8, '\h+', 1)); 

По умолчанию разделителем является пробел. Когда septype не равен 0, это означает, что разделитель должен рассматриваться как подшаблон (поэтому не нужно избегать специальных символов).

Смежные вопросы