У меня есть большая строка str и игла ndl. Теперь мне нужно найти похожий текст ndl из строки str. Например,
ИСТОЧНИК: «Это демонстрационный текст, и я люблю тебя об этом».
ИГЛА: «Я тебя люблю»
ВЫХОД: «Я люблю тебя»
ИСТОЧНИК: «У меня есть уникальная идея. Вам нужна?».
ИГЛА: «Unik IDIA»
ВЫХОД: «уникальная идея»
Я обнаружил, что могу сделать это, используя меры подобия, такие как мера подобия косинуса или манхэттона. Однако я думаю, что реализация этого алгоритма будет сложной. Не могли бы вы предложить мне какой-нибудь простой или быстрый способ сделать это, возможно, используя любую библиотечную функцию php? ТИА
Для достижения этой цели нет встроенной функции 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
Попробуйте этот код, чтобы найти строку в строке
$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";
}
Это очень простой способ сделать это:
$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