Что такое безопасная копия Unicode String.IndexOf(string input), которая может обрабатывать суррогатные пары?

Я пытаюсь найти эквивалент С# string.IndexOf(string), который может обрабатывать суррогатные пары в символах Unicode.

Я могу получить индекс только при сравнении отдельных символов, как в приведенном ниже коде:

    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, это не сработает, потому что каждый текстовый элемент содержит только один символ для сравнения.

Есть ли какие-либо предложения относительно того, как это написать?

Спасибо за любую помощь.

РЕДАКТИРОВАТЬ:

Ниже приведен пример того, почему это необходимо:

КОД

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

ВЫХОД

9
8

Обратите внимание, когда я заменяю символ ???? на @, значения меняются.


person Ibrennan208    schedule 04.05.2018    source источник
comment
используйте одну и ту же кодировку для обеих строк, и вы хорошо   -  person Steve    schedule 04.05.2018
comment
@ Стив, я добавил некоторую информацию к своему вопросу. Являются ли эти строки одной и той же кодировкой или есть разница?   -  person Ibrennan208    schedule 04.05.2018
comment
@Ibrennan208 Ibrennan208, из вашей первоначальной реализации похоже, что вы пытаетесь найти единственную графему, потому что вы используете IndexOf в массиве строк, которые фактически являются TextElements, но из вашего примера данных это выглядит как будто вы действительно хотите найти индекс подстроки длиной › 1 графема. Можете ли вы указать, какое решение вы ищете? (Просто запустите свой код на своих тестовых данных - он не будет работать - indexOf вернет -1)   -  person ironstone13    schedule 04.05.2018
comment
@ ironstone13 Я хочу найти индекс подстроки длиной › 1. В вопросе я объяснил, что могу заставить его работать, если я сравниваю строку только с одним символом, но я хочу расширить его, чтобы учесть пользователю ввести многосимвольную строку, чтобы найти индекс.   -  person Ibrennan208    schedule 04.05.2018


Ответы (1)


В основном вы хотите найти индекс одного массива строк в другом массиве строк. Для этого мы можем адаптировать код из этого вопроса:

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();
        }
    }
}
person Evk    schedule 04.05.2018
comment
Красиво, я писал то же самое, но ты быстрее! - person ironstone13; 05.05.2018
comment
Спасибо, это именно то, что я искал! - person Ibrennan208; 05.05.2018