You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Transliteration类拉丁转西里尔字母时Yu组合识别失败的修复咨询

问题

我正在开发一个Transliteration类,但测试用例LatinToCyrillicTextShouldEqualTheirEqual执行失败,原因是该类无法识别Yu作为组合字符,而是将Y和u分别单独进行转写。请问该如何修复这个问题?

现有代码

Transliteration类

public sealed class Transliteration
{
    private const string CyrillicLowercase = "а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ь ю я";
    private const string CyrillicUppercase = "А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ь Ю Я";
    private const string LatinLowercase = "a b v g d e zh z i y k l m n o p r s t u f h ts ch sh sht a y yu ya";
    private const string LatinUppercase = "A B V G D E Zh Z I Y K L M N O P R S T U F H Ts Ch Sh Sht A Y Yu Ya";
    
    private readonly Dictionary<string,string> _dict;

    private Transliteration()
    {
        _dict = new Dictionary<string, string>();
    }

    private Transliteration(Dictionary<string, string> dict)
    {
        ArgumentNullException.ThrowIfNull(dict);
        
        _dict = dict;
    }
    
    public static Transliteration Create()
    {
        var lowercaseDict = CyrillicLowercase.Split(' ')
            .Zip(LatinLowercase.Split(' '), (k, v) => new { k, v })
            .ToDictionary(x => x.k, x => x.v);

        var uppercaseDict = CyrillicUppercase.Split(' ')
            .Zip(LatinUppercase.Split(' '), (k, v) => new { k, v })
            .ToDictionary(x => x.k, x => x.v);

        var both = lowercaseDict.Concat(uppercaseDict)
            .ToLookup(x => x.Key, x => x.Value)
            .ToDictionary(x => x.Key, g => g.First());

        return new Transliteration(both);
    }
    
    /// <summary>
    /// Transliterates cyrillic text to latin.
    /// </summary>
    /// <param name="text">The text to be transliterated.</param>
    /// <returns>The transliterated text.</returns>
    public string CyrillicToLatin(string text)
    {
        return _dict.Aggregate(text, (current, pair) => current.Replace(pair.Key, pair.Value));
    }
    
    /// <summary>
    /// Transliterates latin text to cyrillic.
    /// </summary>
    /// <param name="text">The text to be transliterated.</param>
    /// <returns>The transliterated text.</returns>
    public string LatinToCyrillic(string text)
    {
        return _dict.Aggregate(text, (current, pair) => current.Replace(pair.Value, pair.Key));
    }
}

测试类

public class TransliterationTests
{
    private readonly Transliteration _transliteration;
    
    public TransliterationTests()
    {
        _transliteration = Transliteration.Create();
    }
    
    [Fact]
    public void CyrillicToLatinTextShouldEqualTheirEqual()
    {
        // Arrange

        
        // Act
        var actual = _transliteration.CyrillicToLatin("Юлия Колева Хаджииванова");

        // Assert
        actual.Should().Be("Yuliya Koleva Hadzhiivanova");
    }
    
    [Fact]
    public void LatinToCyrillicTextShouldEqualTheirEqual()
    {
        // Arrange

        
        // Act
        var actual = _transliteration.LatinToCyrillic("Yuliya Koleva Hadzhiivanova");

        // Assert
        actual.Should().Be("Юлия Колева Хаджииванова");
    }
}

问题原因

核心问题在于:

  1. 双向转换共用同一个字典,且字典键的遍历顺序不固定,无法保证多字符拉丁组合(如Yu、Zh)优先被替换。
  2. 执行LatinToCyrillic时,可能先处理单字符Y或u,导致Yu被拆分为单个字符替换,无法匹配到对应的西里尔字符Ю。

修复方案

为拉丁到西里尔的转换创建单独的映射字典,并确保多字符组合优先处理:

修改后的Transliteration类

public sealed class Transliteration
{
    private const string CyrillicLowercase = "а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ь ю я";
    private const string CyrillicUppercase = "А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ь Ю Я";
    private const string LatinLowercase = "a b v g d e zh z i y k l m n o p r s t u f h ts ch sh sht a y yu ya";
    private const string LatinUppercase = "A B V G D E Zh Z I Y K L M N O P R S T U F H Ts Ch Sh Sht A Y Yu Ya";
    
    private readonly Dictionary<string, string> _cyrillicToLatin;
    private readonly Dictionary<string, string> _latinToCyrillic;

    private Transliteration(Dictionary<string, string> cyrillicToLatin, Dictionary<string, string> latinToCyrillic)
    {
        ArgumentNullException.ThrowIfNull(cyrillicToLatin);
        ArgumentNullException.ThrowIfNull(latinToCyrillic);
        
        _cyrillicToLatin = cyrillicToLatin;
        _latinToCyrillic = latinToCyrillic;
    }
    
    public static Transliteration Create()
    {
        // 构建西里尔到拉丁的映射
        var lowercaseCyrToLat = CyrillicLowercase.Split(' ')
            .Zip(LatinLowercase.Split(' '), (k, v) => new { k, v })
            .ToDictionary(x => x.k, x => x.v);

        var uppercaseCyrToLat = CyrillicUppercase.Split(' ')
            .Zip(LatinUppercase.Split(' '), (k, v) => new { k, v })
            .ToDictionary(x => x.k, x => x.v);

        var cyrillicToLatin = lowercaseCyrToLat.Concat(uppercaseCyrToLat)
            .ToLookup(x => x.Key, x => x.Value)
            .ToDictionary(x => x.Key, g => g.First());

        // 构建拉丁到西里尔的映射,按拉丁字符长度降序排列,确保多字符组合优先替换
        var latinToCyrillicPairs = lowercaseCyrToLat.Select(p => new { Latin = p.Value, Cyrillic = p.Key })
            .Concat(uppercaseCyrToLat.Select(p => new { Latin = p.Value, Cyrillic = p.Key }))
            .OrderByDescending(p => p.Latin.Length)
            .GroupBy(p => p.Latin)
            .ToDictionary(g => g.Key, g => g.First().Cyrillic);

        return new Transliteration(cyrillicToLatin, latinToCyrillicPairs);
    }
    
    public string CyrillicToLatin(string text)
    {
        return _cyrillicToLatin.Aggregate(text, (current, pair) => current.Replace(pair.Key, pair.Value));
    }
    
    public string LatinToCyrillic(string text)
    {
        return _latinToCyrillic.Aggregate(text, (current, pair) => current.Replace(pair.Key, pair.Value));
    }
}

修复说明

  • 拆分双向转换的字典,分别维护_cyrillicToLatin和_latinToCyrillic,避免互相干扰。
  • 构建_latinToCyrillic时,通过OrderByDescending(p => p.Latin.Length)确保多字符组合(如Yu、sht)比单字符(如Y、u)先被处理,从根本上避免拆分替换的问题。
  • 保持原有西里尔到拉丁的转换逻辑不变,确保功能兼容性。

修改后运行测试用例,LatinToCyrillicTextShouldEqualTheirEqual即可正常通过。

内容的提问来源于stack exchange,提问作者nop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:30:30