Как искать шаблоны в произвольных последовательностях?
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