什么是可以处理代理对的String.IndexOf(字符串输入)的Unicode安全副本?

时间:2018-05-04 20:03:05

标签: c# string unicode indexof surrogate-pairs

我试图弄清楚可以处理Unicode字符中的代理项对的C#string.IndexOf(string)

我只能在比较单个字符时获取索引,如下面的代码所示:

    public static int UnicodeIndexOf(this string input, string find)
    {
        return input.ToTextElements().ToList().IndexOf(find);
    }

    public static IEnumerable<string> ToTextElements(this string input)
    {
        var e = StringInfo.GetTextElementEnumerator(input);
        while (e.MoveNext())
        {
            yield return e.GetTextElement();
        }
    }

但是如果我尝试实际使用一个字符串作为find变量,那么它将无法工作,因为每个文本元素只包含一个要比较的字符。

对于如何写这个有什么建议吗?

感谢您的帮助。

编辑:

下面是为什么这是必要的一个例子:

CODE

 Console.WriteLine("HolyCowBUBBYYYYY".IndexOf("BUBB"));
 Console.WriteLine("HolyCow@BUBBYY@YY@Y".IndexOf("BUBB"));

输出

9
8

请注意我将字符替换为@的值会更改。

1 个答案:

答案 0 :(得分:2)

你基本上想要在另一个字符串数组中找到一个字符串数组的索引。我们可以根据https://docs.mongodb.com/manual/reference/operator/aggregation/week/问题调整代码:

public static class Extensions {
    public static int UnicodeIndexOf(this string input, string find, StringComparison comparison = StringComparison.CurrentCulture) {
        return IndexOf(
           // split input by code points
           input.ToTextElements().ToArray(),
           // split searched value by code points
           find.ToTextElements().ToArray(), 
           comparison);
    }
    // code from another answer
    private static int IndexOf(string[] haystack, string[] needle, StringComparison comparision) {
        var len = needle.Length;
        var limit = haystack.Length - len;
        for (var i = 0; i <= limit; i++) {
            var k = 0;
            for (; k < len; k++) {
                if (!String.Equals(needle[k], haystack[i + k], comparision)) break;
            }

            if (k == len) return i;
        }

        return -1;
    }

    public static IEnumerable<string> ToTextElements(this string input) {
        var e = StringInfo.GetTextElementEnumerator(input);
        while (e.MoveNext()) {
            yield return e.GetTextElement();
        }
    }
}