Как найти похожий текст в большой строке?

У меня есть большая строка str и игла ndl. Теперь мне нужно найти похожий текст ndl из строки str. Например,

ИСТОЧНИК: «Это демонстрационный текст, и я люблю тебя об этом».

ИГЛА: «Я тебя люблю»

ВЫХОД: «Я люблю тебя»


ИСТОЧНИК: «У меня есть уникальная идея. Вам нужна?».

ИГЛА: «Unik IDIA»

ВЫХОД: «уникальная идея»

Я обнаружил, что могу сделать это, используя меры подобия, такие как мера подобия косинуса или манхэттона. Однако я думаю, что реализация этого алгоритма будет сложной. Не могли бы вы предложить мне какой-нибудь простой или быстрый способ сделать это, возможно, используя любую библиотечную функцию php? ТИА

1

Решение

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

Как и предполагалось, ваш вопрос предполагает, что вам не нужны простые функции соответствия строк, такие как stripos и co и регулярное выражение не могут этого достичь. Например

уникальный и уникальный

а также

идея и идея

не могут быть сопоставлены этими функциями. Так что нужно искать что-то вроде levenshtein function.Но так как вам нужны подстроки, а не обязательно вся строка, а также, чтобы облегчить работу для levenshtein function и ваш сервер, вы должны использовать воображение. break и то и другое haystack and needle словами, а затем использовать levenshtein чтобы найти наиболее близкие значения для ваших игл.

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

для строк только с ASCII-символами это сравнительно легко достичь. Но для других кодировок вы, вероятно, столкнетесь со многими трудностями. Но простой подход к обработке многобайтовых строк тоже может быть что-то вроде:

     function to_ascii($text,$encoding="UTF-8") {
if (is_string($text)) {
// Includes combinations of characters that present as a single glyph
$text = preg_replace_callback('/\X/u', __FUNCTION__, $text);
}
elseif (is_array($text) && count($text) == 1 && is_string($text[0])) {
// IGNORE characters that can't be TRANSLITerated to ASCII
$text = @iconv($encoding, "ASCII//IGNORE//TRANSLIT", $text[0]);
// The documentation says that iconv() returns false on failure but it returns ''
if ($text === '' || !is_string($text)) {
$text = '?';
}
elseif (preg_match('/\w/', $text)) {        // If the text contains any letters...
$text = preg_replace('/\W+/', '', $text); // ...then remove all non-letters
}
}
else {  // $text was not a string
$text = '';
}
return $text;
}





function find_similar($needle,$str,$keep_needle_order=false){
if(!is_string($needle)||!is_string($str))
{
return false;
}
$valid=array();
//get  encodings  and words from haystack and needle
setlocale(LC_CTYPE, 'en_GB.UTF8');
$encoding_s=mb_detect_encoding($str);
$encoding_n=mb_detect_encoding($needle);

mb_regex_encoding ($encoding_n);
$pneed=array_filter(mb_split('\W',$needle));

mb_regex_encoding ($encoding_s);
$pstr=array_filter(mb_split('\W',$str));



foreach($pneed as $k=>$word)//loop trough needle's words
{
foreach($pstr as $key=>$w)
{
if($encoding_n!==$encoding_s)
{//if $encodings are not the same make some transliteration
$tmp_word=($encoding_n!=='ASCII')?to_ascii($word,$encoding_n):$word;
$tmp_w=($encoding_s!=='ASCII')?to_ascii($w,$encoding_s):$w;
}else
{
$tmp_word=$word;
$tmp_w=$w;
}

$tmp[$tmp_w]=levenshtein($tmp_w,$tmp_word);//collect levenshtein distances
$keys[$tmp_w]=array($key,$w);

}

$nominees=array_flip(array_keys($tmp,min($tmp)));//get the nominees
$tmp=10000;
foreach($nominees as $nominee=>$idx)
{//test sound like to get more precision
$idx=levenshtein(metaphone($nominee),metaphone($tmp_word));
if($idx<$tmp){
$answer=$nominee;//get the winner

}
unset($nominees[$nominee]);
}
if(!$keep_needle_order){
$valid[$keys[$answer][0]]=$keys[$answer][1];//get the right form of the winner
}
else{
$valid[$k]=$keys[$answer][1];
}
$tmp=$nominees=array();//clean a little for the next iteration
}
if(!$keep_needle_order)
{
ksort($valid);
}

$valid=array_values($valid);//get only the values
/*return the array of the closest value to the
needle according to this algorithm of course*/
return $valid;

}


var_dump(find_similar('i knew you love me','finally  i know you loved me and all my pets'));
var_dump(find_similar('I you love','This is a demo text and I love you about this'));
var_dump(find_similar('a unik idia','I have a unique idea. Do you need?'));
var_dump(find_similar("Goebel, Weiss, Goethe, Goethe und Goetz",'Weiß, Goldmann, Göbel, Weiss, Göthe, Goethe und Götz'));
var_dump(find_similar('Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįʈ',
'Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįʈ, șếᶑ ᶁⱺ ẽḭŭŝḿꝋď ṫĕᶆᶈṓɍ ỉñḉīḑȋᵭṵńť ṷŧ ḹẩḇőꝛế éȶ đꝍꞎôꝛȇ ᵯáꞡᶇā ąⱡîɋṹẵ.'));

и вывод:

    array(5) {
[0]=>
string(1) "i"[1]=>
string(4) "know"[2]=>
string(3) "you"[3]=>
string(5) "loved"[4]=>
string(2) "me"}
array(3) {
[0]=>
string(1) "I"[1]=>
string(4) "love"[2]=>
string(3) "you"}
array(3) {
[0]=>
string(1) "a"[1]=>
string(6) "unique"[2]=>
string(4) "idea"}
array(5) {
[0]=>
string(6) "Göbel"[1]=>
string(5) "Weiss"[2]=>
string(6) "Goethe"[3]=>
string(3) "und"[4]=>
string(5) "Götz"}
array(8) {
[0]=>
string(13) "Ḽơᶉëᶆ"[1]=>
string(13) "ȋṕšᶙṁ"[2]=>
string(14) "ḍỡḽǭᵳ"[3]=>
string(6) "ʂǐť"[4]=>
string(11) "ӓṁệẗ"[5]=>
string(26) "ĉṓɲṩḙċťᶒțûɾ"[6]=>
string(23) "ấɖḯƥĭṩčįɳġ"[7]=>
string(9) "ḝłįʈ"}

если вам нужен вывод в виде строки, вы можете использовать join на результат функции перед ее использованием

Вы можете запустить рабочий код и проверить результат онлайн

Но вы должны иметь в виду, что это не будет работать ни для всех типов строк, ни для всех версий PHP

1

Другие решения

Попробуйте этот код, чтобы найти строку в строке

$data = "I have a unique idea. Do you need one?";
$find = "a unique idea";
$start = strpos($data, $find);
if($start){
$end = $start + strlen($find);
print_r(substr($data, $start, strlen($find)));
} else {
echo "not found";
}
0

Это очень простой способ сделать это:

$source = "This is a demo text and I love you about this";
$needle = "I you love";
$words = explode(" " , $source);
$needleWords = explode(" ", $needle);
$results = [];

foreach($needleWords as $key => $needleWord) {

foreach($words as $keyWords => $word) {

if(strcasecmp($word, $needleWord) == 0) {
$results[$keyWords] = $needleWord;
}
}
}
uksort($results, function($a , $b) {
return $a - $b;
});
echo(implode(" " , $results));

Выход

I love you
0
По вопросам рекламы [email protected]