我为此写了一个扩展方法,可以在任何IEnumerable<T>
上使用。
/// <summary>
/// Splits the specified IEnumerable at every element that satisfies a
/// specified predicate and returns a collection containing each sequence
/// of elements in between each pair of such elements. The elements
/// satisfying the predicate are not included.
/// </summary>
/// <param name="splitWhat">The collection to be split.</param>
/// <param name="splitWhere">A predicate that determines which elements
/// constitute the separators.</param>
/// <returns>A collection containing the individual pieces taken from the
/// original collection.</returns>
public static IEnumerable<IEnumerable<T>> Split<T>(
this IEnumerable<T> splitWhat, Func<T, bool> splitWhere)
{
if (splitWhat == null)
throw new ArgumentNullException("splitWhat");
if (splitWhere == null)
throw new ArgumentNullException("splitWhere");
return splitIterator(splitWhat, splitWhere);
}
private static IEnumerable<IEnumerable<T>> splitIterator<T>(
IEnumerable<T> splitWhat, Func<T, bool> splitWhere)
{
int prevIndex = 0;
foreach (var index in splitWhat
.Select((elem, ind) => new { e = elem, i = ind })
.Where(x => splitWhere(x.e)))
{
yield return splitWhat.Skip(prevIndex).Take(index.i - prevIndex);
prevIndex = index.i + 1;
}
yield return splitWhat.Skip(prevIndex);
}
例如,在你的情况,你可以使用它像这样:
var arr = new string[] { "foo", "bar", "jar", "\r", "a", "b", "c", "\r", "x", "y", "z", "\r" };
var results = arr.Split(elem => elem == "\r");
foreach (var result in results)
Console.WriteLine(string.Join(", ", result));
这将打印:
foo, bar, jar
a, b, c
x, y, z
(包括在最后一个空白行,因为有在收藏结束时是"\r"
)。
可能的重复[如何将IEnumerable分成IEnumerable组的几个组(http://stackoverflow.com/questions/1349491/how-can-i-split-an-ienumerablestring-into-groups-of -numeumerablestring) –
James
2010-09-21 10:00:56
不,它不是重复的 - 另一个是要求固定大小的组,这是要求基于分隔符的分割。 – Timwi 2010-09-21 10:10:33
@Timwi:*可能*是关键字在这里.... – James 2010-09-21 14:21:55