基于谓词拆分LINQ查询

我想要一个将IEnumerable分解为谓词的方法,通过它们相对于谓词的索引将项目分组在一起。 例如,它可以在满足x => MyRegex.Match(x).Success项目中拆分List ,其中“中间”项目将这些匹配组合在一起。

它的签名可能看起来像一些线

 public static IEnumerable<IEnumerable> Split( this IEnumerable source, Func predicate, int bool count ) 

,可能还有一个包含所有分隔符的输出的额外元素。

有没有比foreach循环更有效和/或更紧凑的方法来实现它? 我觉得应该可以用LINQ方法实现,但我不能指责它。

例:

 string[] arr = {"One", "Two", "Three", "Nine", "Four", "Seven", "Five"}; arr.Split(x => x.EndsWith("e")); 

以下任何一种都可以:

 IEnumerable {{}, {"Two"}, {}, {"Four", "Seven"}, {}} IEnumerable {{"Two"}, {"Four", "Seven"}} 

存储匹配的可选元素是{"One", "Three", "Nine", "Five"}

您应该通过扩展方法执行此操作(此方法假定您忽略分区项目):

 /// Splits an enumeration based on a predicate. ///  /// This method drops partitioning elements. ///  public static IEnumerable> Split( this IEnumerable source, Func partitionBy, bool removeEmptyEntries = false, int count = -1) { int yielded = 0; var items = new List(); foreach (var item in source) { if (!partitionBy(item)) items.Add(item); else if (!removeEmptyEntries || items.Count > 0) { yield return items.ToArray(); items.Clear(); if (count > 0 && ++yielded == count) yield break; } } if (items.Count > 0) yield return items.ToArray(); } 

如果您希望避免使用扩展方法,则可以始终使用:

 var arr = new[] {"One", "Two", "Three", "Nine", "Four", "Seven", "Five"}; var result = arr.ToLookup(x => x.EndsWith("e")); // result[true] == One Three Nine Five // result[false] == Two Four Seven 
 public static IEnumerable> Split( this IEnumerable source, Func predicate) { List group = new List(); foreach (TSource item in source) { if (predicate(item)) { yield return group.AsEnumerable(); group = new List(); } else { group.Add(item); } } yield return group.AsEnumerable(); } 
 public static IEnumerable> Partition(this IEnumerable source, Func predicate) { yield return source.Where(predicate); yield return source.Where(x => !predicate(x)); } 

例:

 var list = new List { 1, 2, 3, 4, 5 }; var parts = list.Partition(x => x % 2 == 0); var even = parts.ElementAt(0); // contains 2, 4 var odd = parts.ElementAt(1); // contains 1, 3, 5