将西里尔文转换为拉丁文 - 拉丁文 intruders/exception

Convert cyrilic to latin - latin intruders/exception

我正在使用简单的字典将西里尔字母替换为拉丁字母,大多数时候它工作得很好,但是当输入一些拉丁字母时我遇到了问题。大多数时候是公司名称。

几个例子:

PROCRED 正在转换为 RROSRED

ОВЕХ 饰演 OVEH

CITY 作为 SITU

我该怎么办?

这是我正在使用的字典

public string ConvertCyrillicToLatin(string text)
        {
            Dictionary<string, string> words = new Dictionary<string, string>();

            words.Add("А", "A");
            words.Add("Б", "B");
            words.Add("В", "V");
            words.Add("Г", "G");
            words.Add("Д", "D");
            words.Add("Ђ", "Đ");
            words.Add("Е", "E");
            words.Add("Ж", "Ž");
            words.Add("З", "Z");
            words.Add("И", "I");
            words.Add("Ј", "J");
            words.Add("К", "K");
            words.Add("Л", "L");
            words.Add("Љ", "Lj");
            words.Add("М", "M");
            words.Add("Н", "N");
            words.Add("Њ", "Nj");
            words.Add("О", "O");
            words.Add("П", "P");
            words.Add("Р", "R");
            words.Add("С", "S");
            words.Add("Т", "T");
            words.Add("Ћ", "Ć");
            words.Add("У", "U");
            words.Add("Ф", "F");
            words.Add("Х", "H");
            words.Add("Ц", "C");
            words.Add("Ч", "Č");
            words.Add("Џ", "Dž");
            words.Add("Ш", "Š");
            words.Add("а", "a");
            words.Add("б", "b");
            words.Add("в", "v");
            words.Add("г", "g");
            words.Add("д", "d");
            words.Add("ђ", "đ");
            words.Add("е", "e");
            words.Add("ж", "ž");
            words.Add("з", "z");
            words.Add("и", "i");
            words.Add("ј", "j");
            words.Add("к", "k");
            words.Add("л", "l");
            words.Add("љ", "lj");
            words.Add("м", "m");
            words.Add("н", "n");
            words.Add("њ", "nj");
            words.Add("о", "o");
            words.Add("п", "p");
            words.Add("р", "r");
            words.Add("с", "s");
            words.Add("т", "t");
            words.Add("ћ", "ć");
            words.Add("у", "u");
            words.Add("ф", "f");
            words.Add("х", "h");
            words.Add("ц", "c");
            words.Add("ч", "č");
            words.Add("џ", "dž");
            words.Add("ш", "š");

            var source = text;
            foreach (KeyValuePair<string, string> pair in words)
            {
                source = source.Replace(pair.Key, pair.Value);
            }

            return source;
        }

更新 1

根据评论中的要求,这是我的豁免清单:

"СIТУ":"CITY",
"OBEX":"OBEX"

现在只有这两个例子,用于测试,但不可能有一个真正的功能豁免清单,有这么多的可能性。

我希望如果应用程序遇到拉丁字母,只需忽略它并保持原样。它已经像西里尔字母不存在或存在但具有相同含义的拉丁字母那样工作,例如字母 AEODGTEJKLMN ...像С(S), Х(H), У(Y), P(R)...

更新 2

以下是评论中要求的几个输入示例。 斜线符号当然不会出现在输入中,我只是添加它,以便您区分拉丁部分

...ПОВЕРИОЦ /LЕNS OBEX DОО/, У СКЛАДУ СА ОДРЕДИОМ...

...ИЗЈАВА ПРИВРЕДНОГ ДРУШТВА /GRАDЈЕVINSКО РRЕDUZЕСЕ IМРЕХ LОZNIСА/ СА АДРЕСОМ]...[=1

...зззу

...КОРИСТ ПОВЕРИОЦА /ATР BANK TOUR/, СА СЕДИШТЕМ...

在下面的代码中,两个词典用于将带有西里尔字符的文本转换为拉丁字符。如果单词包含拉丁字符,则使用第一个 LatinType 字典。否则使用第二个 CyrillicType

class Program
{
    static void Main(string[] args)
    {
        var text = "...ПОВЕРИОЦ / LЕNS OBEX DОО/, У СКЛАДУ СА ОДРЕДБОМ..."
              + "...ИЗЈАВА ПРИВРЕДНОГ ДРУШТВА / GRАDЈЕVINSКО РRЕDUZЕСЕ IМРЕХ LОZNIСА / СА АДРЕСОМ..."
              + "...ЗА УГОВОР О ОТВАРАЊУ КРЕДИТНЕ ЛИНИЈЕ СА КОМПАНИЈОМ / DOWN CITУ / И РАСПОН МЕСЕЧНЕ КАМАТНЕ СТОПЕ...";

        var result = CyrillicToLatin.Convert(text);
    }
    public static class CyrillicToLatin
    {
        private static readonly Dictionary<string, string> ExclusionList = new()
            {
                { "ОТР COMPANY", "OTP COMPANY" }
            };

        private static readonly Dictionary<char, string> LatinType = new()
        {
            {'А', "A"},
            {'В', "B"},
            {'Е', "E"},
            {'К', "K"},
            {'М', "M"},
            {'Н', "H"},
            {'О', "O"},
            {'Р', "P"},
            {'С', "C"},
            {'Т', "T"},
            {'У', "Y"},
            {'Х', "X"}
        };

        private static readonly Dictionary<char, string> CyrillicType = new()
        {
            { 'А', "A" },
            { 'Б', "B" },
            { 'В', "V" },
            { 'Г', "G" },
            { 'Д', "D" },
            { 'Ђ', "Đ" },
            { 'Е', "E" },
            { 'Ж', "Ž" },
            { 'З', "Z" },
            { 'И', "I" },
            { 'Ј', "J" },
            { 'К', "K" },
            { 'Л', "L" },
            { 'Љ', "Lj" },
            { 'М', "M" },
            { 'Н', "N" },
            { 'Њ', "Nj" },
            { 'О', "O" },
            { 'П', "P" },
            { 'Р', "R" },
            { 'С', "S" },
            { 'Т', "T" },
            { 'Ћ', "Ć" },
            { 'У', "U" },
            { 'Ф', "F" },
            { 'Х', "H" },
            { 'Ц', "C" },
            { 'Ч', "Č" },
            { 'Џ', "Dž" },
            { 'Ш', "Š" },
            { 'а', "a" },
            { 'б', "b" },
            { 'в', "v" },
            { 'г', "g" },
            { 'д', "d" },
            { 'ђ', "đ" },
            { 'е', "e" },
            { 'ж', "ž" },
            { 'з', "z" },
            { 'и', "i" },
            { 'ј', "j" },
            { 'к', "k" },
            { 'л', "l" },
            { 'љ', "lj" },
            { 'м', "m" },
            { 'н', "n" },
            { 'њ', "nj" },
            { 'о', "o" },
            { 'п', "p" },
            { 'р', "r" },
            { 'с', "s" },
            { 'т', "t" },
            { 'ћ', "ć" },
            { 'у', "u" },
            { 'ф', "f" },
            { 'х', "h" },
            { 'ц', "c" },
            { 'ч', "č" },
            { 'џ', "dž" },
            { 'ш', "š" }
        };

        public static string Convert(string text)
        { 
            // Apply the exclusion list first               
            foreach (KeyValuePair<string, string> pair in ExclusionList)
            {
                text = text.Replace(pair.Key, pair.Value);
            }

            string pattern = @"[^,;()\s]+"; // Delimiters 

            var sb = new StringBuilder();
            var index = 0;

            foreach (Match match in Regex.Matches(text, pattern))
            {
                var dictionary = IsContainLatin(match.Value) ? LatinType : CyrillicType;
                var word = ConvertWord(match.Value, dictionary);
                if (index < match.Index)
                {
                    sb.Append(text[index..match.Index]);
                }
                sb.Append(word);
                index = match.Index + match.Length;
            }
            return sb.ToString();
        }

        private static string ConvertWord(string word, Dictionary<char, string> coding)
        {
            var result = new StringBuilder();
            foreach(char c in word)
            {
                string s = c.ToString();
                if (coding.TryGetValue(c, out string val))
                    s = val;
                result.Append(s);
            }
            return result.ToString();
        }

    private static bool IsContainLatin(string s)
        {
            foreach (char c in s)
                if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
                    return true;
            return false;
        }
    }
}

通过此代码,问题“UPDATE 2”中的文本将被编码为以下内容:

...POVERIOC / LENS OBEX DOO/, U SKLADU SA ODREDBOM......IZJAVA PRIVREDNOG DRUŠTVA / GRADЈEVINSKO PREDUZECE IMPEX LOZNICA / SA ADRESOM......ZA UGOVOR O OTVARANjU KREDITNE LINIJE SA KOMPANIJOM / DOWN CITY / I RASPON MESEČNE KAMATNE STOPE...