Как искать шаблоны в произвольных последовательностях?

Regex только для строки, но что делать, если эта функция может быть расширена не только символом, но и объектами или даже функциями? Предположим, что наш объект будет целым числом, они могут быть в любом порядке:

1 2 3 4 5 6 7 8 9 10 11 12 13

И задача, которую вы хотите решить, - найти простые пары (или аналогичную задачу поиска шаблонов) следующим образом:

{prime}{anyNumber}{prime}

Итак, ответ таков:

(3,4,5) (5,6,7) (11,12,13)

Или немного более сложный пример для цепочки простых чисел:

{prime}({anyNumber}{prime})+

Ответ:

(3,(4,5),(6,7)) (11,(12,13))

Как много работает Regex, правильно?

Что происходит, так это то, что вы определяете некоторую функцию с именем isPrime (x) и используете ее, когда вам нужно проверить, является ли следующий элемент ввода действительным простым (так что это какое-то равенство объекту или пространству объекта).

То, что я создал до сих пор

Я создал класс ObjectRegex, похожий на класс Regex в С#. Он принимает шаблоны выше и выполняет предикат, связанный с ним для идентификации объекта. Он работает отлично, но проблема заключается в том, что для работы любой последовательности типа TValue необходимо преобразовать в строку до того, как она будет передана шаблону Regex, и для этого я должен применить ВСЕ предикаты к целой последовательности. O (n * m) - плохая идея после всего....

Я решил обойти это трудным путем и... попытаться наследовать строку, которая запечатана и наследование запрещено. Что нужно от этого унаследованного класса, это переопределить accessor

char this[int index] {get;}

в интересах отсроченного выполнения предикатов до момента, когда он действительно имеет смысл.

Итак, любая идея, как это сделать? Мне нравится .NET Regex и его синтаксис, есть ли способ обойти это проклятие строки и обмануть движок? Может быть, отражение или хардкор я не знаю?

Обновление 1

Я нашел эту статью http://www.codeproject.com/Articles/463508/NET-CLR-Injection-Modify-IL-Code-during-Run-time и думаю, что это может быть сделано путем замены этого метода [int index] на мой код, но я думаю, что это повредит все остальное, потому что вы просто не можете заменить метод только для одного экземпляра.

Ответы

Ответ 1

Наследование строк

После некоторых исследований я обнаружил, что идея оптимизировать существующее Regex невозможно. Это связано с тем, что даже если я знаю индекс в строке, у меня все еще нет доступа к возможным состояниям в авторежиме Regex, которые я должен искать для фильтрации ненужных вычислений.

ORegex

Что касается ответа, я решил реализовать свой собственный движок, похожий на механизм Microsoft Regex. Синтаксис совпадает с синтаксисом Microsoft Regex. Вы можете найти дополнительную информацию и примеры на Nuget и github:

В настоящее время он поддерживает основные функции механизма Regex, а также некоторые популярные функции, такие как просмотр и захват.

Пример

public static bool IsPrime(int number)
{
    int boundary = (int)Math.Floor(Math.Sqrt(number));
    if (number == 1) return false;
    if (number == 2) return true;
    for (int i = 2; i <= boundary; ++i)
    {
        if (number % i == 0) return false;
    }
    return true;
}

public void PrimeTest()
{
    var oregex = new ORegex<int>("{0}(.{0})*", IsPrime);
    var input = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
    foreach (var match in oregex.Matches(input))
    {
        Trace.WriteLine(string.Join(",", match.Values));
    }
}

//OUTPUT:
//2
//3,4,5,6,7
//11,12,13