给定源IEnumerable<T>
和正整数偏移量以及合并函数Func<T,T,TResult>
我想生成一个新的IEnumerable<TResult>
可能的签名如下:
public static IEnumerable<TResult> Offset<T, TResult>(
this IEnumerable<T> source, int offset, Func<T,T,TResult> selector
);
这是一个使用以下输入的示例,它将产生可枚举的偏移量并选择偏移部分的总和。
typeof(T) = typeof(int);
typeof(TResult) = typeof(int);
source = Enumerable.Range(0, 10);
offset = 1;
selector = (original, offsetValue) => original + offsetValue;
result = source.Offset(offset, selector);
expected = new int[]{1,3,5,7,9,11,13,15,17};
Assert.IsTrue(expected.SequenceEquals(result));
此处一个非常重要的目标是仅枚举来源IEnumerable<T>
。
答案 0 :(得分:2)
您需要跟踪以前的offset
项目。 Queue
可能是执行此操作的最有效工具。如果所述队列中有足够的项目,则将当前项目与出队项目配对并生成它。
public static IEnumerable<TResult> Offset<T, TResult>(
this IEnumerable<T> source, int offset, Func<T, T, TResult> selector)
{
var queue = new Queue<T>(offset);
foreach (var item in source)
{
if (queue.Count >= offset)
yield return selector(queue.Dequeue(), item);
queue.Enqueue(item);
}
}
答案 1 :(得分:1)
嗯,听起来你需要缓冲结果,例如在数组中:
public static IEnumerable<TResult> Offset<T, TResult>(
this IEnumerable<T> source, int offset, Func<T,T,TResult> selector)
{
// TODO: Shenanigans to validate arguments eagerly
T[] buffer = new T[offset];
using (var iterator = source.GetEnumerator())
{
for (int i = 0; i < offset && iterator.MoveNext(); i++)
{
buffer[i] = iterator.Current;
}
int index = 0;
while (iterator.MoveNext())
{
T old = buffer[index];
T current = iterator.Current;
yield return selector(old, current);
buffer[index] = current;
index = (index + 1) % offset;
}
}
}
这至少适用于你的例子......