我发现这篇文章正在寻找同样的东西,但对答案非常不满意(大多数似乎是关于加入字符串 [?],并且接受的答案似乎很冗长)。所以我最终只是想出了一些其他的方法来做到这一点。
我更喜欢这样的方式:
public static IEnumerable<T> AfterEach <T> (this IEnumerable<T> source, T delimiter) =>
source.SelectMany((item) => Enumerable.Empty<T>().Append(item).Append(delimiter));
或者,或者:
public static IEnumerable<T> AfterEach <T> (this IEnumerable<T> source, T delimiter) =>
source.SelectMany((item) => new T[] { item, delimiter });
它们都是等价的:对于每个 item,创建一个新序列 { item, delimiter },然后使用 SelectMany 将它们连接在一起。 p>
另一种方法,不是单一的,但可能更容易阅读并且非常简单:
public static IEnumerable<T> AfterEach <T> (this IEnumerable<T> source, T delimiter) {
foreach (T item in source) {
yield return item;
yield return delimiter;
}
}
如果您不想要在末尾添加额外的分隔符,方法类似,除了您连接 { delimiter, item } 序列,然后 Skip 额外开头的分隔符(这比在末尾跳过一个更高效)。
public static IEnumerable<T> Delimit <T> (this IEnumerable<T> source, T delimiter) =>
source.SelectMany((item) => Enumerable.Empty<T>().Append(delimiter).Append(item)).Skip(1);
public static IEnumerable<T> Delimit <T> (this IEnumerable<T> source, T delimiter) =>
source.SelectMany((item) => new T[] { delimiter, item }).Skip(1);
收益方法是这样的(同样,两个相似的选项,只是取决于你的感觉):
public static IEnumerable<T> Delimit <T> (this IEnumerable<T> source, T delimiter) {
foreach (T item in source.Take(1)) // protects agains empty source
yield return item;
foreach (T item in source.Skip(1)) {
yield return delimiter;
yield return item;
}
}
public static IEnumerable<T> Delimit <T> (this IEnumerable<T> source, T delimiter) {
static IEnumerable<U> Helper<U> (IEnumerable<U> source, U delimiter) {
foreach (U item in source) {
yield return delimiter;
yield return item;
}
}
return Helper(source, delimiter).Skip(1);
}
有一些可运行的示例和测试代码(用于Delimit,而不是AfterEach)here。那里也有一个带有Aggregate 的实现,我认为这里不值得写。它可以以类似的方式适应AfterEach。