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