Większość osób, które z jakiś sposób mają kontakt z systemami do masowej wysyłki wiadomości e-mail, prędzej czy później staną przez zadaniem automatycznej personalizacji imion osób do których wysyłamy wiadomość. W niema prawie w każdym podręczniku traktującym to zagadnienie pisze wielkimi literami, że do takiej osoby powinniśmy zwracać się osobiście.
Większość osób po prostu pisze „Witaj Krzysztof!” ale jak można zauważyć w e-mailach dostawanych od „dużych” firm pojawia się sformułowanie „Witaj Krzysztofie” i tu stajemy przed „wielkim gramatycznym” problemem, bo nasze rodzime imiona odmienia się różnie. Inaczej odmieniają się żeńskie, a inaczej męskie imiona, ale na dodatek jeszcze wszystko zależy od końcówki imienia.
Więc trzeba podciągnąć rękawy i zabrać się za robotę.
Na pierwszy ogień idą imiona żeńskie, bo z nimi jest prawie najłatwiej. Jeśli imię kończy się na „a”, a w 99% przypadków tak właśnie jest to po prostu odcinamy to „a” i zmieniamy na „o”, a pozostałe 1% trzeba trochę pokombinować.
$sImie = 'Anna';
$sDoDodawnia = "";
if(!preg_match("/(e|i|o|u|y)$/iu", $sImie))
{
if(preg_match("/(.*)a$/iu", $sImie, $aImieTmp))
{
if(preg_match("/(ia)$/iu", $sImie, $aImie))
{
preg_match("/(.*)ia$/iu", $sImie, $aImieTest);
$sZnak = end(str_split($aImieTest[1]));
switch($sZnak)
{
case 'r':
case 'n': $sDoDodawnia = "o"; break;
default: $sDoDodawnia = "no"; break;
}
}
elseif(preg_match("/(n{1,2}a)$/iu", $sImie, $aImie) ||
preg_match("/(ja)$/iu", $sImie, $aImie))
{
$sDoDodawnia = "o";
$aImieTmp[1] = preg_replace('#(n){2,}#iu', 'n', $aImieTmp[1]);
}
elseif(preg_match("/(l{1,2}a)$/iu", $sImie, $aImie))
{
$sDoDodawnia = "u";
if(preg_match("/(l{2}a)$/iu", $sImie, $aImie))
$sDoDodawnia = "o";
$aImieTmp[1] = preg_replace('#(l){2,}#iu', 'l', $aImieTmp[1]);
}
elseif(preg_match("/(([^c]i)|([^ansz])a)$/iu", $sImie, $aImie))
{
$sDoDodawnia = "o";
}
}
}
$sImie = $sImieTmp[1].$sDoDodawnia;
// Wynik: Anno
I w sumie mamy załatwione w ten sposób sporą liczbę imion żeńskich.
Co z męskimi? Tutaj już jest bardzo pod górkę, ponieważ w zależności od końcówki odmiana imienia jest prawie zawsze inna, ale i z tym można sobie poradzić. Do naszego już istniejącego kodu dodajemy odpowiednio kolejne zasady gramatyczne. Całej zawiłej gramatyki języka polskiego w tej kwestii nie będę tłumaczył (nie jestem polonistą), jest to ponad moje siły. Całość opiera się na tej samej zasadzie co powyżej, czyli sprawdzamy pewną część imienia i podejmujemy odpowiednią akcję.
$sImie = 'Krzysztof';
function odmianaImion($sImie)
{
$sDoDodawnia = "";
$aCzlony = explode(' ', $sImie);
if(count($aCzlony) > 1)
{
foreach($aCzlony AS $iK => $sImie)
$aCzlony[$iK] = odmianaImion($sImie);
return implode(' ', $aCzlony);
}
else
{
if(!preg_match("/(e|i|o|u|y)$/iu", $sImie))
{
if(preg_match("/(.*)a$/iu", $sImie, $aImieTmp))
{
if(preg_match("/(ia)$/iu", $sImie, $aImie))
{
preg_match("/(.*)ia$/iu", $sImie, $aImieTest);
$sZnak = end(str_split($aImieTest[1]));
switch($sZnak)
{
case 'r':
case 'n': $sDoDodawnia = "o"; break;
default: $sDoDodawnia = "no"; break;
}
}
elseif(preg_match("/(n{1,2}a)$/iu", $sImie, $aImie) ||
preg_match("/(ja)$/iu", $sImie, $aImie))
{
$sDoDodawnia = "o";
$aImieTmp[1] = preg_replace('#(n){2,}#iu', 'n', $aImieTmp[1]);
}
elseif(preg_match("/(l{1,2}a)$/iu", $sImie, $aImie))
{
$sDoDodawnia = "u";
if(preg_match("/(l{2}a)$/iu", $sImie, $aImie))
$sDoDodawnia = "o";
$aImieTmp[1] = preg_replace('#(l){2,}#iu', 'l', $aImieTmp[1]);
}
elseif(preg_match("/(([^c]i)|([^ansz])a)$/iu", $sImie, $aImie))
{
$sDoDodawnia = "o";
}
}
elseif(preg_match("/(c|g|k)$/iu", $sImie) &&
preg_match("/(.*?)([clnsz]ie|)(e|)(c|g|k)$/iu", $sImie, $aImieTmp))
{
if(!empty($aImieTmp[2]))
{
switch($aImieTmp[2])
{
case "cie": $sDoDodawnia = "ć"; break;
case "lie": $sDoDodawnia = "ł"; break;
case "nie": $sDoDodawnia = "ń"; break;
case "sie": $sDoDodawnia = "ś"; break;
case "zie": $sDoDodawnia = "ź"; break;
default: $sDoDodawnia = "u"; break;
}
}
elseif($aImieTmp[3] == 'e') // np. 'Franciszek'
{
$sDoDodawnia = "ku";
}
}
elseif(preg_match("/(h|j|l|sz|cz|rz|ż|Ż)$/iu", $sImie) &&
preg_match("/(.*)/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "u";
}
elseif(preg_match("/(b|f|m|n|p|s|v|w|[^src]z)$/iu", $sImie) &&
preg_match("/(.*)/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "ie";
}
elseif(preg_match("/(t)$/iu", $sImie) &&
preg_match("/(.*)t/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "cie";
}
elseif(preg_match("/(d)$/iu", $sImie) &&
preg_match("/(.*)/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "zie";
}
elseif(preg_match("/(ł)$/iu", $sImie) &&
preg_match("/(.*?)(e|)(ł)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "le";
}
elseif(preg_match("/(ń)$/iu", $sImie) &&
preg_match("/(.*)(ń)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "cie";
}
elseif(preg_match("/(ź)$/iu", $sImie) &&
preg_match("/(.*)(ź)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "cie";
}
elseif(preg_match("/(ś)$/iu", $sImie) &&
preg_match("/(.*)(ś)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "cie";
}
elseif(preg_match("/(x)$/iu", $sImie) &&
preg_match("/(.*)(x)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "ksie";
}
elseif(preg_match("/(r)$/iu", $sImie) &&
preg_match("/(.*?)(e|)(r)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = "rze";
}
}
elseif(preg_match("/(e|i|o|u|y)$/iu", $sImie) &&
preg_match("/(.*)(e|i|o|u|y)$/iu", $sImie, $aImieTmp))
{
$sDoDodawnia = $aImieTmp[2];
}
return $aImieTmp[1].$sDoDodawnia;
}
}
echo odmianaImion($sImie);
// Wynik: Krzysztofie
I to tyle, wiem że nie jest to w 100% wyczerpany temat ale w ten sposób można sobie nieźle uprościć życie. Rzeczy, które trzeba dodatkowo zaimplementować to np. wyjątki, bo co zrobić z imieniem Mercedes, napiszemy „Witaj Mercedesie!”? Raczej nam nie chodzi o auto, a o osobę.
Zaprezentowany algorytm jest skuteczny tylko przy imionach polskich i odmienianych zgodnie z zasadami naszej gramatyki. Imiona obcojęzyczne odmieniają się już całkowicie inaczej i powyższa funkcja traci swój sens.
Innym podejściem do tematu jest stworzenie ogromnej bazy danych imion i ich odmian, co jest bardzo trudne, ale tutaj przychodzi nam również z pomocą internet i jego zasoby.
Korzystając bazy imion przeprowadziłem test poprawności mojej funkcji i okazało się, że na 1711 pozycji, błędnych jest tylko 183, co daje niecałe 10,7% błędnych odmian, co chyba nie jest takim złym wynikiem.
GitHub Source
Mam nadzieję, że choć trochę pomogłem. Zachęcam do napisania cennych opinii i doświadczeń na ten temat w komentarzach, aby podzielić się nimi z innymi programistami i przyjaciółmi.
PICTURE CREDITS
