ОБСУЖДЕНИЕ

Функция склонения имени и фамилии

11 сообщений1 просмотровЗакрыта
#1
В общем функцию склонения существительного после числительного я нашел, а вот фамилию имя блин гугл не помогает просклонять.. Функция должна быть без запросов к левым сайтам =)
===
с меня 10 р, кто поможет для прокачки кошелька :D
UPD: поднимаю до 15 р ставку :D
#2
initrd, http://masteram.us/codes/info/215
#3
bot, [Sun Jan 11 15:10:32.658693 2015] [:error] [pid 4861] [client 127.0.0.1:40268] PHP Fatal error: Call to undefined function utf_strlen() in /home/sergey/www/ibic.com/SITE/templates/text/distributors/distributors.php on line 4383
#4
initrd, Вот склонение имени:
PHP
//склоняет имя, учитывая пол $s(1 - мужской, 0 - женский)
//падеж $p (1 - именительный; 2 - родительный; 3 - дательный; 4 - винительный; 5 - творительный; 6 - предложный)
function smart_name($name, $s, $p){
$f_end1 = array('ла','ка','ша','ра','ня','тя','на','га','ля','та','да','са','ия','дя','ся','ья','вь','ва','оя','за','ая','ма','фа','йа');
$f_end2 = array('лы','ки','ши','ры','ни','ти','ны','ги','ли','ты','ды','сы','ии','ди','си','ьи','ви','вы','ои','зы','аи','мы','фы','йи');
$f_end3 = array('ле','ке','ше','ре','не','те','не','ге','ле','те','де','се','ии','де','се','ье','ви','ве','ое','зе','ае','ме','фе','йе');
$f_end4 = array('лу','ку','шу','ру','ню','тю','ну','гу','лю','ту','ду','су','ию','дю','сю','ью','вь','ву','ою','зу','аю','му','фу','йю');
$f_end5 = array('лой','кой','шей','рой','ней','тей','ной','гой','лей','той','дой','сой','ией','дей','сей','ьей','вью','вой','оей','зой','аей','мой','фой','йей');
$f_end6 = array('ле','ке','ше','ре','не','те','не','ге','ле','те','де','се','ии','де','се','ье','ви','ве','ое','зе','ае','ме','фе','йе');
$m_end1 = array('ма','ас','ша','ей','ня','ик','ва','рь','ля','лл','им','кс','тя','ад','ан','ат','ий','ха','ём','ем','ян','ис','ай','ир','ав','эн','ен','ег','ил','еб','ев','ам','он','ид','рп','ин','ор','ст','от','иф','кс','ар','та','нт','рх','тр','ум','ов','рк','ьф','ед','ьд','кт','ьм','яс','их','ет','ия','ья','ак','рт','рл');
$m_end2 = array('мы','аса','ши','ея','ни','ика','вы','ря','ли','лла','има','кса','ти','ада','ана','ата','ия','хи','ёма','ема','яна','иса','ая','ира','ава','эна','ена','ега','ила','еба','ьва','ама','она','ида','рпа','ина','ора','ста','ота','ифа','кса','ара','ты','нта','рха','тра','ума','ова','рка','ьфа','еда','ьда','кта','ьма','яса','иха','ета','ия','ьи','ака','рта','рла');
$m_end3 = array('ме','асу','ше','ею','не','ику','ве','рю','ле','ллу','иму','ксу','те','аду','ану','ату','ию','хе','ёму','ему','яну','ису','аю','иру','аву','эну','ену','егу','илу','ебу','ьву','аму','ону','иду','рпу','ину','ору','сту','оту','ифу','ксу','ару','те','нту','рху','тру','уму','ову','рку','ьфу','еду','ьду','кту','ьму','ясу','иху','ету','ию','ье','аку','рту','рлу');
$m_end4 = array('му','аса','шу','ея','ню','ика','ву','ря','лю','лла','има','кса','тю','ада','ана','ата','ия','ху','ёму','ему','яна','иса','ая','ира','ава','эна','ена','ега','ила','еба','ьва','ама','она','ида','рпа','ина','ора','ста','ота','ифа','кса','ара','ту','нта','рха','тра','ума','ова','рка','ьфа','еда','ьда','кта','ьма','яса','иха','ета','ия','ью','ака','рта','рла');
$m_end5 = array('мой','аом','шей','еем','ней','иком','вой','рем','лей','ллом','има','ксом','тей','адом','аном','атом','ием','хой','ёмом','емом','яном','исом','аем','иром','авом','эном','еном','егом','илом','ебом','ьвом','амом','оном','идом','рпом','ином','ором','стом','отом','ифом','ксом','аром','той','нтом','рхом','тром','умом','овом','рком','ьфом','едом','ьдом','ктом','ьмом','ясом','ихом','етом','ием','ьёй','аком','ртом','рлом');
$m_end6 = array('ме','асе','ше','ее','не','ике','ве','ре','ле','лле','име','ксе','те','аде','ане','ате','ии','хе','ёме','еме','яне','исе','ае','ире','аве','эне','ене','еге','иле','ебе','ьве','аме','оне','иде','рпе','ине','оре','сте','оте','ифе','ксе','аре','те','нте','рхе','тре','уме','ове','рке','ьфе','еде','ьде','кте','ьме','ясе','ихе','ете','ие','ье','аке','рте','рле');
$name = strtolower($name);
$num = strlen($name);
$r = ucfirst($name);
$lch = $name{$num-2}.$name{$num-1};
if($s == 0) {
$amount = count($f_end1);
if(in_array($lch, $f_end1)) {
if($p == 2) {
for($i=0;$i<$amount;$i++)
($lch==$f_end1[$i])?$ch=$f_end2[$i]:0;
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if($p == 3) {
for($i=0;$i<$amount;$i++)
($lch==$f_end1[$i])?$ch=$f_end3[$i]:0;
(($lch=='ия')&&($num>3))?$ch='ии':0;
(($lch=='ия')&&($num<4))?$ch='ие':0;
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if($p == 4) {
for($i=0;$i<$amount;$i++)
($lch==$f_end1[$i])?$ch=$f_end3[$i]:0;
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if ($p == 5) {
for($i=0;$i<$amount;$i++)
($lch==$f_end1[$i])?$ch=$f_end3[$i]:0;
$name{$num} = $ch{2};
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if ($p == 6) {
for($i=0;$i<$amount;$i++)
($lch==$f_end1[$i])?$ch=$f_end3[$i]:0;
(($lch=='ия')&&($num>3))?$ch='ии':0;
(($lch=='ия')&&($num<4))?$ch='ие':0;
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
}
}
if ($s == 1) {
$amount = count($m_end1);
if(in_array($lch, $m_end1)) {
if ($p == 2) {
for($i=0;$i<$amount;$i++)
($lch==$m_end1[$i])?$ch=$m_end2[$i]:0;
$name{$num} = $ch{2};
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if ($p == 3) {
for($i=0;$i<$amount;$i++)
($lch==$m_end1[$i])?$ch=$m_end3[$i]:0;
$name{$num} = $ch{2};
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if ($p == 4) {
for($i=0;$i<$amount;$i++)
($lch==$m_end1[$i])?$ch=$m_end4[$i]:0;
$name{$num} = $ch{2};
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if ($p == 5) {
for($i=0;$i<$amount;$i++)
($lch==$m_end1[$i])?$ch=$m_end5[$i]:0;
$name{$num+1} = $ch{3};
$name{$num} = $ch{2};
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
if ($p == 6) {
for($i=0;$i<$amount;$i++)
($lch==$m_end1[$i])?$ch=$m_end6[$i]:0;
$name{$num} = $ch{2};
$name{$num-1} = $ch{1};
$name{$num-2} = $ch{0};
$r = ucfirst($name);
}
}
}
return $r;
}

Функция расчитана на склонение русских имён, если вдруг, я упустил какое-то имя, Вы можете самостоятельно добавить его. Для этого нужно во все 6 массивов добавить окончания этого имени.


После, я случаянно наткнулся на сервис Яндекса Склонятор. А после на функцию, которая поможет склонять имена, фамилии и даже некоторые ники и слова. Хороша она тем, что не требует указания рода, и можно подавать на склонение целую фразу, например ф.и.о. Курьян Станислав Олегович. Со своей задачей она справляется превосходно. Вот код функции:
function inflect($name) {
$url = 'http://export.yandex.ru/inflect.xml?name='.urlencode($name);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.6.30 Version/10.61');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
curl_close($curl);
$cases = array();
preg_match_all('#\<inflection\s+case\=\"([0-9]+)\"\>(.*?)\<\/inflection\>#si', $result, $m);
if ( count($m[0]) ) {
foreach ($m[1] as $i => &$id) {
$cases[(int)$id] = $m[2][$i];
} unset ($id);
} else return null;
if (count($cases) > 1) return $cases;
else return false;
}

Как видите функция компактнее. Возвращает массив склонённых слов.
Для того, чтобы явно указать падеж, можно дописать ещё одну небольшую функцию s_name(), у которой в качестве входящих параметров выступает 
склоняемое имя и падеж.
function s_name($name, $p) {
$cases = inflect($name);
if ($cases && count($cases) > 1) return iconv("UTF-8", "Windows-1251", $cases[$p]);
else return iconv("UTF-8", "Windows-1251", $name);
}

Функция возвращает склонённое имя в кодировке UTF-8, поэтому я использовал функцию iconv() для преобразования в CP1251.

ща фамилии найду)
#5
bot, Надо 2 в 1 :D
#6
initrd, Ищу)
#7
bot, Спасибо :D
#8
initrd,
PHP
<? 
function changename($changename = 'Пупкин Василий', $gender = 1, $case = 1) { 

// Разделяем данные на фамилию и имя 
$partname = explode(' ', $changename); 

// Если падеж не именительный, начинаем работу 
if ($case > 1) { 

// Получаем фамилию и имя 
$sn = $partname['0']; 
$n = $partname['1']; 

// Получаем длину фамилии и имени ( кол-во символов ) 
$lsn = utf_strlen($sn); 
$ln = utf_strlen($n); 

// Получаем длину фамилии и имени до предпоследней буквы ( кол-во символов ) 
$m1sn = $lsn - 1; 
$m1n = $ln - 1; 
$m2n = $ln - 2; 

// Выводим последние символы ( окончания ) для дальнейшего сравнения с окончаниями в массиве 
$e1sn = utf_substr($sn, $m1sn, 1); 
$e1n = utf_substr($n, $m1n, 1); 
$e2n = utf_substr($n, $m2n, 2); 

// Получаем фамилию и имя без последних символов 
$n1esn = utf_substr($sn, 0, $m1sn); 
$n1en = utf_substr($n, 0, $m1n); 
$n2en = utf_substr($n, 0, $m2n); 

// Работа с мужской фамилией и именем 
if ($gender == 1) { 

// Массив окончаний мужских фамилий 
$mesn = array( 
'1' => array( 'о', 'х') 
); 

// Замена окончаний фамилии в зависимости от падежа 
$snlc = ($case == 2) ? 'а' : ($case == 3) ? 'у' : ''; 

// Замена окончаний фамилий в зависимости от падежа 
if (in_array($e1sn, $mesn['1'])) { 
$surname = $sn; 
} else { 
$surname = $sn . $snlc; 
} 

// Массив окочаний мужских имен 
$men = array( 
'1' => array( 'ва', 'ма' ), 
'2' => array( 'ек'), 
'3' => array('ел'), 
'4' => array( 'н', 'р', 'в', 'с', 'м', 'л', 'д' ), 
'5' => array( 'й', 'ь' ), 
'6' => array( 'я', 'а' ) 
); 

// Работа с заменой окончаний мужских имен в зависимости от падежа 
if ($name = in_array($e2n, $men['1'])) { 
$nlc = ($case == 2) ? 'ы' : ($case == 3) ? 'е' : ''; 
$name = $n1en . $nlc; 
} elseif (in_array($e2n, $men['2'])) { 
$nlc = ($case == 2) ? 'ька' : ($case == 3) ? 'ьку' : ''; 
$name = $n2en . $nlc; 
} elseif(in_array($e2n, $men['3'])) { 
$nlc = ($case == 2) ? 'ла' : ($case == 3) ? 'лу' : ''; 
$name = $n2en . $nlc; 
} elseif(in_array($e1n, $men['4'])) { 
$nlc = ($case == 2) ? 'а' : ($case == 3) ? 'у' : ''; 
$name = $n . $nlc; 
} elseif (in_array($e1n, $men['5'])) { 
$nlc = ($case == 2) ? 'я' : ($case == 3) ? 'ю' : ''; 
$name = $n1en . $nlc; 
} elseif (in_array($e1n, $men['6'])) { 
$nlc = ($case == 2) ? 'и' : ($case == 3) ? 'е' : ''; 
$name = $n1en . $nlc; 
} else { 
$name = $n; 
} 

// Работа с женской фамилией и именем 
} elseif ($gender == 2) { 

// Массив окончаний женских фамилий 
$wesn = array( 
'1' => array( 'о', 'х') 
); 

// Замена окончаний фамилий в зависимости от падежа 
if (in_array($e1sn, $wesn['1'])) { 
$surname = $sn; 
} else { 
$surname = $n1esn . 'ой'; 
} 

// Массив окончаний женских имен 
$wen = array( 
'1' => array( 'ша', 'тя', 'ня', 'ка', 'ля' ), 
'2' => array( 'ра', 'та', 'да', 'ма', 'на' ) 
); 


// Работа с заменой окончаний женских имен в зависимости от падежа 
if ($name = in_array($e2n, $wen['1'])) { 
$wlc = ($case == 2) ? 'и' : ($case == 3) ? 'е' : ''; 
$name = $n1en . $wlc; 
} elseif (in_array($e2n, $wen['2'])) { 
$wlc = ($case == 2) ? 'ы' : ($case == 3) ? 'е' : ''; 
$name = $n1en . $wlc; 
} else { 
$name = $n; 
} 

// Если каким то образом пол не определен то ничего не меняем 
} else { 
$surname = $sn; 
$name = $n; 
} 

// Соединяем измененные фамилию и имя 
$fullname = $surname . ' ' . $name; 

// Если падеж именительный то ничего не изменяем 
} else { 
$fullname = $changename; 
} 
// 
return $fullname; 
} 
Параметры и их значения
Первый параметр - фамилия и имя в именительном падеже (если правило не будет соблюдено возможна некорректное склонение).
Второй - пол пользователя, где:
1 - мужской
2 - женский
Третий - падеж склонения, где:
1 - именительный (кто, что)
2 - родительный (кого, чего)
3 - дательный (кому, чему)
Вызывая функцию и ПРАВИЛЬНО указав все параметры вы получите фамилию и имя склоненные по выбранному вами падежу
Вызов и результат
<?=changename('Пупкин Вася', 1, 3)?>
попробуй эт)
#9
bot, Та же, что и в кодах.. utf_substr() неизвестная..
#10
bot, все же нашел сам + немного переписал =) выложил в коды.

Бот - кошелек в личку за попытки помочь =)
#11
Тему закрыл initrd!
Причина: Нашел функцию =)