Добрый день. Пытаюсь сделать морфологический разбор слов (не русский язык). Дело такое, язык - агглютинативный, что немного упрощает задачу. Агглютинация - явление, когда словообразование происходит за счёт прибавления окончания. При этом действует правило: одна морфема - одно окончание. Как я понимаю, из-за особенностей языка, разбор нужно проводить с конца, проверяя совпадение окончания одно за другим. Условно, есть набор окончаний: PHP: $affiks = array( '0' => array( 'mı', 'mi', 'mu', 'mü' ), '1' => array( 'im', 'ım' ), '2' => array( 'lar', 'lər' ), ); Есть слово: akraba-lar-ım Нужно разобрать слово, чтобы получилось следующее: akraba - основа lar - индекс 2 im - индекс 1 Делаю так: PHP: foreach ( $affiks as $id => $ends ) { foreach ( $ends as $end ) { if ( preg_match( '/' . $end . '$/', 'akrabalarım' ) ) { $result .= 'Найдено окончание: ' . $end . ' с ID: ' . $id; } } } Однако выводит пока "Найдено окончание: ım с ID: 1" Буду благодарен за любую помощь.
Есть быстрый вариант (по количеству правок кода), но тут важен порядок окончаний (расположение в массиве): PHP: $word = 'akrabalarım'; foreach ( $affiks as $id => $ends ) { foreach ( $ends as $end ) { if ( preg_match( '/^(.+)' . $end . '$/', $word, $m) ) { $result .= 'Найдено окончание: ' . $end . ' с ID: ' . $id; $word = $m[1]; } } } $result .= 'Основа: ' . $word; В слове akrabaımlar найдет только lar
@Yankovitz хз может можно проще: PHP: affiks = array( '0' => array( 'mı', 'mi', 'mu', 'mü' ), '1' => array( 'im', 'ım' ), '2' => array( 'lar', 'lər' ), ); $name = 'akrabalarim'; $result = ''; $base = ''; $parse = parse($affiks, $name, $result, $base); echo $parse; function parse($arr, $str, $result, $base){ foreach($arr as $id => $ends){ foreach ($ends as $end) { $pos = strripos($str, $end); if ($pos !== false) { $result .= 'Найдено окончание: '.$end.' с ID: '.$id.'<br>'; $base = substr($str, 0, $pos); parse($arr, $base, $result, $base); } } } $result .= $base.' - основа'; return $result; }
ВЫЗЫВАЙТЕ РУМИЛАНА! @johovich , приди!!! Он на этой хрени собаку съел и даже расширение для пыха написал, которое под такое дело годится.
У меня такой вариант ) PHP: $affiks = array( '0' => array( 'mı', 'mi', 'mu', 'mü' ), '1' => array( 'im', 'ım' ), '2' => array( 'lar', 'lər' ), ); $word = 'akrabalarım'; $word_parts = []; function disassemble ($affiks, $word) { global $word_parts; foreach ($affiks as $end_group => $ends) { foreach ($ends as $end) { $reg_exp = '/(' . $end . '){1}$/'; $result = preg_replace($reg_exp, '', $word); // Если преобразование по регулярке произошло, то записываем в массив $word_parts индекс группы аффиксов и выходим обоих циклов. Группу аффиксов удаляем из массива, чтобы не проверять повторно. if ($result !== $word) { //echo "ID: " . $end_group . " " . $end . " " . $result . "<br>"; $word_parts[] = [$end, $end_group]; unset ($affiks[$end_group]); break 2; } } } return ($result === $word) ? [$result, 'основа'] : (disassemble($affiks, $result)); } $word_parts[] = disassemble($affiks, $word); var_dump($word_parts); На выходе: Код (Text): array(3) { [0]=> array(2) { [0]=> string(3) "ım" [1]=> int(1) } [1]=> array(2) { [0]=> string(3) "lar" [1]=> int(2) } [2]=> array(2) { [0]=> string(6) "akraba" [1]=> string(12) "основа" } }
@Ivan Vanko, как на счёт akrabalarimmilərmü https://valick.000webhostapp.com//morpheus.php?word=akrabalarimmilərmü
Тут, мне кажется, надо в тонкости языка уже вникать. Сколько там может быть этих окончаний? Может ли окончание одного типа быть и в самом хвосте слова, и заодно еще перед каким нибудь суффиксом. Думаю, там максимум цепочка из 3х окончаний (суффиксов, аффиксов) будет. И по идее они должны быть уникальные в одном слове. Поэтому использованную в одном цикле группу аффиксов я предложил больше не рассматривать в последующих циклах.
По-моему автор забил на топик. А так все окончания можно запихнуть в одну регулярку. Все зависит от того
Какая разница сколько окончаний если это окончания? https://valick.000webhostapp.com//m...milərlarimmilərlarimmilərlarimmilərlarimmilər
Это верное замечание. В слове не может быть одновременно нескольких вариаций одного окончания: akrabalarım - да, akraba-lar-ım-ım, akraba-lar-lar-ım - нет То есть, в исходно массиве: Код (Text): $affiks = array( '0' => array( 'mı', 'mi', 'mu', 'mü' ), '1' => array( 'im', 'ım' ), '2' => array( 'lar', 'lər' ), '2' => array( 'da', 'də' ), ); Один элемент массива - одно окончание с несколькими вариациями. По сути, количество окончаний может быть теоретически не ограничено, - сколько есть. Например: akraba-lar-ım-da-mı --- Добавлено --- Простите, я просто немого закрутился. Возвращаюсь в тему
@Yankovitz, т.е. надо вывести ошибку если окончания повторяются? В любом случае ссылка есть, можете любые слова пробовать.
И ещё один момент. Проверку нужно делать с окончаний в последовательности с наиболее длинных к менее длинным. Так как есть помимо окончаний array( 'lar', 'lər' ) есть ещё array( 'ar', 'ər' ), Это чтобы такое разделение не происходило: akrabal-ar-ım (что не верно) --- Добавлено --- У меня почему-то не работает ссылка
Есть: Код (Text): $affiks = array( '0' => array( 'na', 'nı', 'a', 'ı' ), '1' => array( 'acaq', 'əcək' ), '2' => array( 'am', 'əm' ), '3' => array( 'an', 'ən' ), '4' => array( 'ca', 'cə' ), '5' => array( 'casına', 'cəsinə' ), '6' => array( 'mı', 'mi', 'mu', 'mü' ), '7' => array( 'çı', 'çi', 'çu', 'çü' ), '8' => array( 'da', 'də' ), '9' => array( 'dan', 'dən' ), '10' => array( 'lar', 'lər' ), '11' => array( 'daş' ), '12' => array( 'dı', 'di', 'du', 'dü' ), '13' => array( 'dığı', 'diyi', 'duğu', 'düğü' ), '14' => array( 'dır', 'dir', 'dur', 'dür' ), '15' => array( 'dırlar', 'dirlər', 'durlar', 'dürlər' ), '16' => array( 'sı', 'si', 'su', 'sü', 'ı', 'i', 'u', 'ü' ), '17' => array( '(n)ı', '(n)i', '(n)u', '(n)ü' ), '18' => array( 'ıb', 'ib', 'ub', 'üb' ), '19' => array( 'ıq', 'ik', 'uq', 'ük' ), '20' => array( 'ım', 'im', 'um', 'üm' ), '21' => array( 'ın', 'in', 'un', 'ün' ), '22' => array( 'nın', 'nin', 'nun', 'nün', 'ın', 'in', 'un', 'ün' ), '23' => array( '(y)ın', '(y)in', '(y)un', '(y)ün' ), '24' => array( 'ımız', 'imiz', 'umuz', 'ümüz' ), '25' => array( 'ınız', 'iniz', 'unuz', 'ünüz' ), '26' => array( 'yır', 'yir', 'yur', 'yür', 'ır', 'ir', 'ur', 'ür' ), '27' => array( 'yırdı', 'yirdi', 'yurdu', 'yürdü', 'ırdı', 'irdi', 'urdu', 'ürdü' ), '28' => array( 'lı', 'li', 'lu', 'lü' ), '29' => array( 'lıq', 'lik', 'luq', 'lük' ), '30' => array( 'maq', 'mək' ), '31' => array( 'malı', 'məli' ), '32' => array( 'mı', 'mi', 'mu', 'mü' ), '33' => array( 'mışdı', 'mişdi', 'muşdu', 'müşdü' ), '34' => array( 'saydı', 'səydi' ), '35' => array( 'sa', 'sə' ), '36' => array( 'sən', 'san' ), '37' => array( 'sınız', 'siniz', 'sunuz', 'sünüz' ), '38' => array( 'sız', 'siz', 'suz', 'süz' ), '39' => array( 'sın', 'sin', 'sun', 'sün' ), '40' => array( 'n' ), '41' => array( 'm' ), );
@Yankovitz, не пробовали обратный массив? Ключи - окончания, а идентификаторы - значения. --- Добавлено --- И что вот тут значат скобки? PHP: '23' => array( '(y)ın', '(y)in', '(y)un', '(y)ün' ), Это символы, которые используются в слове?
Можно пробежаться по всему массиву этих окончаний, проверить каждое из них на вхождение его в состав других окончаний (в конце), составить статистику и по ней отсортировать группы окончаний и окончания в каждой группе. И оно само выйдет так, что первыми окажутся группы с самыми длинными окончаниями. Примитивно, конечно, но можно попробовать.
@Ivan Vanko, не нужно. @Maputo дал подсказку, массив надо обратный и одномерный. Думай в этом направлении.
Да, тоже пришел к такому выводу. Сортировка всех окончаний по принципу имен в файловой системе, только их все предварительно надо развернуть (отразить). За каждым закрепить индекс группы. И исключать эти окончания из слов в том порядке, в каком они естественным образом окажутся