private static T[] DoArray <T>(Pair previous, IRegex <T> regex, IList <T> sequence, int count) where T : IComparable <T> { int length = previous.End - previous.Begin + regex.GetSubsequence(count - 1).Count; T[] ans = new T[length]; for (int j = 0; j < length; j++) { ans[j] = sequence[j + previous.Begin]; } return(ans); }
/// <summary> /// where method a la LINQ for IRegex objects, return all subsequences /// that satisfy the IRegex object /// </summary> /// <typeparam name="T"> must implement IComparable of <typeparamref name="T"/></typeparam> /// <param name="sequence">initial sequence</param> /// <param name="function">function that must return regex object for any first (object) argument</param> /// <returns> /// all subsequences a la regex through IEnumerable interface (lazy) /// </returns> public static IEnumerable <IList <T> > Where <T>(this IList <T> sequence, Func <object, IRegex <T> > function) where T : IComparable <T> { //get input regex and check of the correctness IRegex <T> regex = function(null); int count = regex.CountOfSubsequences; if (count == 0) { throw new Exception("Uncorrect regex!"); } if (regex.IsFirstAny) { throw new Exception("FirstAny!"); } if (regex.IsLastAny) { throw new Exception("LastAny!"); } //initialization for the algorithm int[] positions = new int[count]; for (int i = 0; i < count; i++) { int next = sequence.Find(i == 0 ? 0 : positions[i - 1] + regex.GetSubsequence(i - 1).Count, regex.GetSubsequence(i)); if (next == -1) { yield break; } positions[i] = next; } // pair with begin and end of the previous answer Pair previous = new Pair(positions[0], positions[count - 1]); while (true) { bool isFind = false; for (int i = count - 1; i >= 0; i--) { // move first which can int next = sequence.Find(positions[i] + 1, regex.GetSubsequence(i)); if (next < 0) { continue; } positions[i] = next; isFind = true; //try to move others for (int j = i + 1; j < count; j++) { next = sequence.Find(positions[j - 1] + regex.GetSubsequence(j - 1).Count, regex.GetSubsequence(j)); if (next == -1) { isFind = false; break; } positions[j] = next; } //if all is good, then return the result if (isFind) { Pair current = new Pair(positions[0], positions[count - 1]); if (current == previous) { break; } T[] ans = DoArray(previous, regex, sequence, count); //change previous result for future previous = current; yield return(ans); break; } } if (!isFind) { yield return(DoArray(previous, regex, sequence, count)); ; yield break; } } }