[0.1.2] Автоматический поиск ФИО в строке.

This commit is contained in:
Andriy Chaika 2011-05-05 10:06:35 +03:00
parent c582dc176c
commit 4852bbd11f
12 changed files with 24717 additions and 83 deletions

View File

@ -7,7 +7,7 @@
*
* @license Dual licensed under the MIT or GPL Version 2 licenses.
* @author Андрей Чайка http://seagull.net.ua/ bymer3@gmail.com
* @version 0.1.1 03.05.2011
* @version 0.1.2 05.05.2011
*
*/
@ -793,104 +793,103 @@ class NCLNameCaseRu
if (isset($this->fatherName) and $this->fatherName)
{
$LastTwo = mb_substr($this->fatherName, -2, 2, 'utf-8');
if ($LastTwo=='ич')
if ($LastTwo == 'ич')
{
$this->gender=NCLNameCaseRu::$MAN; // мужчина
$this->gender = NCLNameCaseRu::$MAN; // мужчина
return true;
}
if ($LastTwo=='на')
if ($LastTwo == 'на')
{
$this->gender=NCLNameCaseRu::$WOMAN; // женщина
$this->gender = NCLNameCaseRu::$WOMAN; // женщина
return true;
}
}
$man=0; //Мужчина
$woman=0; //Женщина
$FLastSymbol=mb_substr($this->firstName, -1, 1, 'utf-8');
$FLastTwo=mb_substr($this->firstName, -2, 2, 'utf-8');
$FLastThree=mb_substr($this->firstName, -3, 3, 'utf-8');
$FLastFour=mb_substr($this->firstName, -4, 4, 'utf-8');
$SLastSymbol=mb_substr($this->secondName, -1, 1, 'utf-8');
$SLastTwo=mb_substr($this->secondName, -2, 2, 'utf-8');
$SLastThree=mb_substr($this->secondName, -3, 3, 'utf-8');
$man = 0; //Мужчина
$woman = 0; //Женщина
$FLastSymbol = mb_substr($this->firstName, -1, 1, 'utf-8');
$FLastTwo = mb_substr($this->firstName, -2, 2, 'utf-8');
$FLastThree = mb_substr($this->firstName, -3, 3, 'utf-8');
$FLastFour = mb_substr($this->firstName, -4, 4, 'utf-8');
$SLastSymbol = mb_substr($this->secondName, -1, 1, 'utf-8');
$SLastTwo = mb_substr($this->secondName, -2, 2, 'utf-8');
$SLastThree = mb_substr($this->secondName, -3, 3, 'utf-8');
//Если нет отчества, то определяем по имени и фамилии, будем считать вероятность
if (isset($this->firstName) and $this->firstName)
{
//Попробуем выжать максимум из имени
//Если имя заканчивается на й, то скорее всего мужчина
if($FLastSymbol=='й')
if ($FLastSymbol == 'й')
{
$man+=0.9;
}
if(in_array($FLastTwo, array('он', 'ов', 'ав', 'ам','ол', 'ан', 'рд', 'мп')))
if (in_array($FLastTwo, array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп')))
{
$man+=0.3;
}
if($this->in($FLastSymbol,$this->consonant))
if ($this->in($FLastSymbol, $this->consonant))
{
$man+=0.01;
}
if($FLastSymbol=='ь')
if ($FLastSymbol == 'ь')
{
$man+=0.02;
}
if(in_array($FLastTwo, array('вь', 'фь', 'ль')))
if (in_array($FLastTwo, array('вь', 'фь', 'ль')))
{
$woman+=0.1;
}
if(in_array($FLastTwo, array('ла')))
if (in_array($FLastTwo, array('ла')))
{
$woman+=0.04;
}
if(in_array($FLastTwo, array('то', 'ма')))
if (in_array($FLastTwo, array('то', 'ма')))
{
$man+=0.01;
}
if(in_array($FLastThree, array('лья','вва','ока','ука', 'ита')))
if (in_array($FLastThree, array('лья', 'вва', 'ока', 'ука', 'ита')))
{
$man+=0.2;
}
if(in_array($FLastThree, array('има')))
if (in_array($FLastThree, array('има')))
{
$woman+=0.15;
}
if(in_array($FLastThree, array('лия', 'ния', 'сия','дра','лла','кла')))
if (in_array($FLastThree, array('лия', 'ния', 'сия', 'дра', 'лла', 'кла')))
{
$woman+=0.5;
}
if(in_array($FLastFour, array('льда', 'фира', 'нина','лита')))
if (in_array($FLastFour, array('льда', 'фира', 'нина', 'лита')))
{
$woman+=0.5;
}
}
if (isset($this->secondName) and $this->secondName)
{
if(in_array($SLastTwo, array('ов','ин', 'ев', 'ий', 'ёв','ый', 'ын','ой')))
if (in_array($SLastTwo, array('ов', 'ин', 'ев', 'ий', 'ёв', 'ый', 'ын', 'ой')))
{
$man+=0.4;
}
if(in_array($SLastThree, array('ова', 'ина', 'ева', 'ёва', 'ына','ая')))
if (in_array($SLastThree, array('ова', 'ина', 'ева', 'ёва', 'ына', 'ая')))
{
$woman+=0.4;
}
if(in_array($SLastTwo, array('ая')))
if (in_array($SLastTwo, array('ая')))
{
$woman+=0.4;
}
}
//Теперь смотрим, кто больше набрал
if($man>$woman)
if ($man > $woman)
{
$this->gender = NCLNameCaseRu::$MAN;
}
@ -900,18 +899,164 @@ class NCLNameCaseRu
}
}
}
/*
* Автоматическое определение пола
* Возвращает пол по ФИО
* @return integer
*/
public function genderAutoDetect()
{
$this->gender=null;
$this->gender = null;
$this->genderDetect();
return $this->gender;
}
/*
* Определение текущее слово есть фамилией, именем или отчеством
* @return integer $number - 1-фамили 2-имя 3-отчество
*/
private function detectNamePart($namepart)
{
$LastSymbol = mb_substr($namepart, -1, 1, 'utf-8');
$LastTwo = mb_substr($namepart, -2, 2, 'utf-8');
$LastThree = mb_substr($namepart, -3, 3, 'utf-8');
$LastFour = mb_substr($namepart, -4, 4, 'utf-8');
//Считаем вероятность
$first = 0;
$second = 0;
$father = 0;
//если смахивает на отчество
if (in_array($LastThree, array('вна', 'чна', 'вич', 'ьич')))
{
$father+=3;
}
//Похоже на имя
if (in_array($LastThree, array('тин', 'тын')))
{
$first+=0.5;
}
//Исключения
if (in_array($namepart, array('Лев', 'Яков', 'Мальвина', 'Антонина', 'Альбина', 'Агриппина', 'Каллиник', 'Маша', 'Ольга', 'Еремей', 'Фаина', 'Лазарь', 'Екатерина', 'Карина', 'Марина', 'Валентина', 'Кристина', 'Исак', 'Исаак', 'Валентин', 'Константин', 'Мартин', 'Устин', 'Калина', 'Аделина', 'Алина', 'Ангелина', 'Галина', 'Каролина', 'Павлина', 'Полина', 'Элина', 'Мина', 'Нина')))
{
$first+=10;
}
//похоже на фамилию
if (in_array($LastTwo, array('ов', 'ин', 'ев', 'ёв', 'ый', 'ын', 'ой', 'ко', 'ук', 'як', 'ца', 'их', 'ик', 'ун', 'ок', 'ша', 'ая', 'га', 'ёк', 'аш', 'ив', 'юк', 'ус', 'це', 'ак', 'бр')))
{
$second+=0.4;
}
if (in_array($LastThree, array('ова', 'ева', 'ёва', 'ына', 'тых', 'рик', 'вач', 'аха', 'шен', 'мей', 'арь', 'вка', 'шир', 'бан', 'тин', 'чий', 'ина')))
{
$second+=0.4;
}
if (in_array($LastFour, array('ьник', 'нчук', 'тник', 'кирь', 'ский', 'шена')))
{
$second+=0.4;
}
$max = max(array($first, $second, $father));
if ($first == $max)
{
return 'N';
}
elseif ($second == $max)
{
return 'S';
}
else
{
return 'F';
}
}
/*
* Разбиение фразы на слова и определение, где имя, где фамилия, где отчество
* @return string $format - формат имен и фамилий
*/
public function splitFullName($fullname)
{
$this->firstName = '';
$this->secondName = '';
$this->fatherName = '';
$this->gender = null;
$fullname = trim($fullname);
$list = explode(' ', $fullname);
$found = array();
$duplicate = array();
$c = count($list);
for ($i = 0; $i < $c; $i++)
{
if (trim($list[$i]))
{
$found[$i] = $this->detectNamePart($list[$i]);
}
}
$look = array('S' => false, 'F' => false, 'N' => false);
//Первая пробежка - ищем дупликаты
foreach ($found as $key => $letter)
{
if ($look[$letter]) //Если уже есть
{
$duplicate[$key] = $letter;
}
else
{
$look[$letter] = true;
}
}
//Вторая пробежка - тасуем дупликаты
foreach ($duplicate as $key => $letter)
{
if (!$look['S'])
{
$found[$key] = 'S';
}
elseif (!$look['F'])
{
$found[$key] = 'F';
}
elseif (!$look['N'])
{
$found[$key] = 'N';
}
else
{
$found[$key] = ''; //4 слова одно игнорируем
}
}
$format = '';
foreach ($found as $key => $letter)
{
if ($letter == 'S')
{
$this->secondName = $list[$key];
}
elseif ($letter == 'N')
{
$this->firstName = $list[$key];
}
elseif ($letter == 'F')
{
$this->fatherName = $list[$key];
}
$format.=$letter.' ';
}
return trim($format);
}
/*
* Склонение имени
@ -1186,7 +1331,19 @@ class NCLNameCaseRu
{
return $this->srule;
}
/*
* Быстрое склонение имени. Передается один параметр строка, где может быть ФИО в любом виде. Есть необязательный параметр пол. И так ще необязательный параметр падеж. Если падеж указан, тогда возвращается строка в том падеже, если нет тогда все возможные падежи.
*
* @return string
*/
public function q($fullname, $caseNum=null, $gender=null)
{
$format=$this->splitFullName($fullname);
$this->gender=$gender;
$this->genderAutoDetect();
return $this->getFormatted($caseNum, $format);
}
}
?>

View File

@ -3,8 +3,6 @@
## Туториал
Встроенные константы
-----------
* NCLNameCaseRu::$MAN - мужской пол
* NCLNameCaseRu::$WOMAN - женский пол
* NCLNameCaseRu::$IMENITLN - именительный падеж
* NCLNameCaseRu::$RODITLN - родительные падеж
@ -12,43 +10,41 @@
* NCLNameCaseRu::$VINITELN - винительный падеж
* NCLNameCaseRu::$TVORITELN - творительный падеж
* NCLNameCaseRu::$PREDLOGN - предложный падеж
Описание формата вывода
-----------
* S - фамилия
* N - имя
* F - отчество
Пример использования
-----------
echo 'Отчет, ' .
$nc->qFullName("Афонин", "Николай", "Сергеевич", NCLNameCaseRu::$MAN, NCLNameCaseRu::$RODITLN)
$nc->q("Афонин Николай Сергеевич", NCLNameCaseRu::$RODITLN)
. ' о проделаной работе вместе с его сыном ' .
$nc->qFullName("Афонин", "Никита", "", NCLNameCaseRu::$MAN, NCLNameCaseRu::$TVORITELN, "N S") .
' на осенних каникулах. Задание держалось ' .
$nc->qFullName("", "Маргаритта", "Николаевна", NCLNameCaseRu::$WOMAN, NCLNameCaseRu::$PREDLOGN, "на N F; ") .
'Поздравляем всех предчастных, в том числе и ' .
$nc->qFullName("Кардонский", "Серафим", "Ильич", NCLNameCaseRu::$MAN, NCLNameCaseRu::$VINITELN) . ' и ' .
$nc->qFullName("Лобудская", "София", "Викторовна", NCLNameCaseRu::$WOMAN, NCLNameCaseRu::$VINITELN) .
$nc->q("Афонин Никита", NCLNameCaseRu::$TVORITELN) .
' на осенних каникулах. Задание держалось на ' .
$nc->q("Маргаритта Николаевна", NCLNameCaseRu::$PREDLOGN) .
'; Поздравляем всех предчастных, в том числе и ' .
$nc->q("Кардонский Серафим Ильич", NCLNameCaseRu::$VINITELN) . ' и ' .
$nc->q("Лобудская София Викторовна", NCLNameCaseRu::$VINITELN) .
'. Хотим передать поздравление также ' .
$nc->qFullName("Игнатьев", "Павел", "Викторович", NCLNameCaseRu::$MAN, NCLNameCaseRu::$DATELN) . ' и ' .
$nc->qFullName("Сумарский", "Лев", "", NCLNameCaseRu::$MAN, NCLNameCaseRu::$DATELN, "S N");
$nc->q("Игнатьев Павел Викторович", NCLNameCaseRu::$DATELN) . ' и ' .
$nc->q("Сумарский Лев", NCLNameCaseRu::$DATELN);
Результат выполнения
-----------
Отчет, Афонина Николая Сергеевича о проделаной работе вместе с его сыном Никитой Афониным на осенних каникулах. Задание держалось на Маргаритте Николаевне; Поздравляем всех предчастных, в том числе и Кардонского Серафима Ильича и Лобудскую Софию Викторовну. Хотим передать поздравление также Игнатьеву Павлу Викторовичу и Сумарскому Льву
Дополнительно
Отчет, Афонина Николая Сергеевича о проделаной работе вместе с его сыном Афониным Никитой на осенних каникулах. Задание держалось на Маргаритте Николаевне; Поздравляем всех предчастных, в том числе и Кардонского Серафима Ильича и Лобудскую Софию Викторовну. Хотим передать поздравление также Игнатьеву Павлу Викторовичу и Сумарскому Льву
Документация
-----------
Полная документация находится в разработке.
Дополнительные демонстрации находятся в папке Tutorial
Лицензия
-----------
Dual licensed under the MIT or GPL Version 2 licenses.
## 0.1.2 (2011-05-05)
- Написана функция поиска имени, фамилии, отчества в строке.
- Добавлена функция быстрого склонения NCLNameCaseRu::q(), которая принимает обязательный параметр ФИО в любом формате и возвращает строку в нужно падеже.
## 0.1.1 (2011-05-03)
- Написана функция определения пола NCLNameCaseRu::GenderAutoDetect() — отлично справляется с парами Имя Фамилия, по моим тестам дает 100% прохождение тестов (2000 пар имен и фамилий). Если указано отчество, пол определает без проблем.Для просто имен вероятность правильного определения больше 98,5%. Для просто фамилий — больше 96%.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
<?php
class TestGenerator
{
public $maintemplate;
public $testtemplate;
public $resultArrB=array();
public $resultArrG=array();
private $gender;
private $tests;
private $count=0;
public function __construct()
{
//$this->resultArr[]=file('Names/boy_full_result.txt');
//$this->resultArr[]=file('Names/girl_full_result.txt');
}
public function generate($fname)
{
$this->maintemplate = file_get_contents('Template/NCLNameCaseRuTest.main');
$this->testtemplate = file_get_contents('Template/GenderGen'.$fname.'.test');
$this->resultArrB=file('Names/boy_SF.txt');
$this->resultArrG=file('Names/girl_SF.txt');
$this->count=0;
$this->gender=1;
//foreach ($this->resultArr as $key=>$value)
//{
//$this->gender=$key+1;
foreach ($this->resultArrB as $id=>$name)
{
$t=explode(' ', trim($name));
$this->generateTest(trim($t[0]),trim($t[1]));
}
$this->gender=2;
//foreach ($this->resultArr as $key=>$value)
//{
//$this->gender=$key+1;
foreach ($this->resultArrG as $id=>$name)
{
$t=explode(' ', trim($name));
$this->generateTest(trim($t[0]),trim($t[1]));
}
//}
$res=str_replace('{% tests %}', $this->tests, $this->maintemplate);
$res=str_replace('{% name %}', $fname, $res);
file_put_contents('../Library/GenderDetect'.$fname.'.php',$res);
}
private function generateTest($sname, $fname)
{
$tpl=$this->testtemplate;
$tpl=str_replace('{% id %}', $this->count, $tpl);
$tpl=str_replace('{% name %}', $fname, $tpl);
$tpl=str_replace('{% sname %}', $sname, $tpl);
$tpl=str_replace('{% gender %}', $this->gender, $tpl);
$this->tests.=$tpl;
$this->count++;
}
}
$p= new TestGenerator;
$p->generate('Both');
?>

View File

@ -0,0 +1,73 @@
<?php
class TestGenerator
{
public $maintemplate;
public $testtemplate;
public $resultArrB=array();
public $resultArrG=array();
private $gender;
private $tests;
private $count=0;
public function __construct()
{
//$this->resultArr[]=file('Names/boy_full_result.txt');
//$this->resultArr[]=file('Names/girl_full_result.txt');
}
public function generate($fname)
{
$this->maintemplate = file_get_contents('Template/NCLNameCaseRuTest.main');
$this->testtemplate = file_get_contents('Template/GenderGen'.$fname.'.test');
$this->resultArrB=file('NamesAll/boy'.$fname.'.txt');
$this->resultArrG=file('NamesAll/girl'.$fname.'.txt');
$this->count=0;
$this->gender=1;
//foreach ($this->resultArr as $key=>$value)
//{
//$this->gender=$key+1;
foreach ($this->resultArrB as $id=>$name)
{
$this->generateTest(trim($name));
}
$this->gender=2;
//foreach ($this->resultArr as $key=>$value)
//{
//$this->gender=$key+1;
foreach ($this->resultArrG as $id=>$name)
{
$this->generateTest(trim($name));
}
//}
$res=str_replace('{% tests %}', $this->tests, $this->maintemplate);
$res=str_replace('{% name %}', $fname, $res);
file_put_contents('../Library/GenderDetect'.$fname.'.php',$res);
}
private function generateTest($name)
{
$tpl=$this->testtemplate;
$tpl=str_replace('{% id %}', $this->count, $tpl);
$tpl=str_replace('{% name %}', $name, $tpl);
$tpl=str_replace('{% gender %}', $this->gender, $tpl);
$this->tests.=$tpl;
$this->count++;
}
}
$p= new TestGenerator;
$p->generate('name');
$p= new TestGenerator;
$p->generate('sirname');
?>

View File

@ -0,0 +1,7 @@
public function testGenDetect{% id %}()
{
$this->object->setFirstName('{% name %}');
$this->object->setSecondName('{% sname %}');
$this->assertEquals('{% gender %}-{% name %} {% sname %}', $this->object->genderAutoDetect().'-{% name %} {% sname %}');
}

View File

@ -0,0 +1,6 @@
public function testGenDetect{% id %}()
{
$this->object->setFirstName('{% name %}');
$this->assertEquals('{% gender %}-{% name %}', $this->object->genderAutoDetect().'-{% name %}');
}

View File

@ -0,0 +1,6 @@
public function testGenDetect{% id %}()
{
$this->object->setSecondName('{% name %}');
$this->assertEquals('{% gender %}-{% name %}', $this->object->genderAutoDetect().'-{% name %}');
}

View File

@ -14,42 +14,32 @@ $nc = new NCLNameCaseRu();
* =========================
* Встроенные константы
* =========================
* NCLNameCaseRu::$MAN - мужской пол
* NCLNameCaseRu::$WOMAN - женский пол
*
* NCLNameCaseRu::$IMENITLN - именительный падеж
* NCLNameCaseRu::$RODITLN - родительные падеж
* NCLNameCaseRu::$DATELN - дательные падеж
* NCLNameCaseRu::$VINITELN - винительный падеж
* NCLNameCaseRu::$TVORITELN - творительный падеж
* NCLNameCaseRu::$PREDLOGN - предложный падеж
*
* ========================
* Описание формата вывода
* ========================
* S - фамилия
* N - имя
* F - отчество
*/
echo 'Отчет, ' .
$nc->qFullName("Афонин", "Николай", "Сергеевич", NCLNameCaseRu::$MAN, NCLNameCaseRu::$RODITLN)
$nc->q("Афонин Николай Сергеевич", NCLNameCaseRu::$RODITLN)
. ' о проделаной работе вместе с его сыном ' .
$nc->qFullName("Афонин", "Никита", "", NCLNameCaseRu::$MAN, NCLNameCaseRu::$TVORITELN, "N S") .
' на осенних каникулах. Задание держалось ' .
$nc->qFullName("", "Маргаритта", "Николаевна", NCLNameCaseRu::$WOMAN, NCLNameCaseRu::$PREDLOGN, "на N F; ") .
'Поздравляем всех предчастных, в том числе и ' .
$nc->qFullName("Кардонский", "Серафим", "Ильич", NCLNameCaseRu::$MAN, NCLNameCaseRu::$VINITELN) . ' и ' .
$nc->qFullName("Лобудская", "София", "Викторовна", NCLNameCaseRu::$WOMAN, NCLNameCaseRu::$VINITELN) .
$nc->q("Афонин Никита", NCLNameCaseRu::$TVORITELN) .
' на осенних каникулах. Задание держалось на ' .
$nc->q("Маргаритта Николаевна", NCLNameCaseRu::$PREDLOGN) .
'; Поздравляем всех предчастных, в том числе и ' .
$nc->q("Кардонский Серафим Ильич", NCLNameCaseRu::$VINITELN) . ' и ' .
$nc->q("Лобудская София Викторовна", NCLNameCaseRu::$VINITELN) .
'. Хотим передать поздравление также ' .
$nc->qFullName("Игнатьев", "Павел", "Викторович", NCLNameCaseRu::$MAN, NCLNameCaseRu::$DATELN) . ' и ' .
$nc->qFullName("Сумарский", "Лев", "", NCLNameCaseRu::$MAN, NCLNameCaseRu::$DATELN, "S N");
$nc->q("Игнатьев Павел Викторович", NCLNameCaseRu::$DATELN) . ' и ' .
$nc->q("Сумарский Лев", NCLNameCaseRu::$DATELN);
/*
* ========================
* Результат выполнения
* ========================
* Отчет, Афонина Николая Сергеевича о проделаной работе вместе с его сыном Никитой Афониным на осенних каникулах. Задание держалось на Маргаритте Николаевне; Поздравляем всех предчастных, в том числе и Кардонского Серафима Ильича и Лобудскую Софию Викторовну. Хотим передать поздравление также Игнатьеву Павлу Викторовичу и Сумарскому Льву
* Отчет, Афонина Николая Сергеевича о проделаной работе вместе с его сыном Афониным Никитой на осенних каникулах. Задание держалось на Маргаритте Николаевне; Поздравляем всех предчастных, в том числе и Кардонского Серафима Ильича и Лобудскую Софию Викторовну. Хотим передать поздравление также Игнатьеву Павлу Викторовичу и Сумарскому Льву
*/

12
Tutorial/test.php Normal file
View File

@ -0,0 +1,12 @@
<?php
header('Content-type: text/html; charset=utf-8');
/*
* Небольшой пример использования библиотеки
* 1. Шаг подключаем библиотеку
*/
require '../Library/NCL.NameCase.ru.php';
/*
* 2. Создаем объект
*/
$nc = new NCLNameCaseRu();
print_r($nc->qFullName("Рижиков", "Тарас", "Геннадиевич", NCLNameCaseRu::$MAN, NCLNameCaseRu::$DATELN));