如何在C#中将Unicode字符串拆分成多个Unicode字符?

10
如果我有一个字符串,例如"123‍‍‍",我该如何将其拆分为数组,使其看起来像["", "1", "2", "3", "‍‍‍"]?如果使用ToCharArray(),第一个表情符号会被拆分为2个字符,第二个表情符号会被拆分为7个字符。 更新 现在解决方案如下:
public static List<string> GetCharacters(string text)
{
    char[] ca = text.ToCharArray();
    List<string> characters = new List<string>();
    for (int i = 0; i < ca.Length; i++)
    {
        char c = ca[i];
        if (c > ‭65535‬) continue;
        if (char.IsHighSurrogate(c))
        {
            i++;
            characters.Add(new string(new[] { c, ca[i] }));
        }
        else
            characters.Add(new string(new[] { c }));
    }
    return characters;
}

请注意,如评论所述,此方法无法处理家庭表情符号。它仅适用于字符数不超过2个字符的表情符号。示例的输出将为:["", "1", "2", "3", "‍", "‍", "‍", ""]

2
++ = 2,真有趣,我不知道。 - fubo
1
这是怎么发生的?Emoji 是用于文本渲染引擎的。处理包含 Emoji 的文本大致相当于处理中文文本的乐趣。或者,如果你想要一个真正的挑战,可以尝试处理 Zalgo :) 识别代理项并不是什么难事,只需使用 Char.IsLowSurrogate() 即可。 - Hans Passant
2个回答

5
.NET使用UTF-16元素序列来表示字符串。位于基本多文种平面以外的Unicode代码点将被拆分成高位替代项和低位替代项。每个替代项的低10位形成实际代码点值的一半。可以使用辅助函数检测这些替代项(例如Char.IsLowSurrogate)。需要自行处理。

你有关于这些代理函数如何工作的文档或文章吗? - mjw
1
@mjw 请查看编辑(感谢问题评论者帮我记起来)。 - Richard

3

有一个解决方案似乎可以解决您指定的输入问题:

static string[] SplitIntoTextElements(string input)
{
    IEnumerable<string> Helper()
    {
        for (var en = StringInfo.GetTextElementEnumerator(input); en.MoveNext();)
            yield return en.GetTextElement();
    }
    return Helper().ToArray();
}

点击此处尝试


PS:此解决方案适用于.NET 5及以上版本,以前的.NET版本存在错误,会导致分割不正确。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接