Zmiana Krzysztof, na Krzysztofie

calendar_today2018-05-01 folder PHP /  Programowanie

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

Skontaktuj się z nami

keyboard_arrow_up Zadzwoń