I have a list of numbers and I'd like to sel开发者_运维百科ect a sliding window of a certain size:
List<double> lst = {3,78,24,25,634,25,478,24};
int WindowSize = 4;
index = 0: return {3};
index = 1: return {3,78};
index = 2: return {3,78,24};
index = 3: return {3,78,24,25};
index = 4: return {78,24,25,634};
index = 5: return {24,25,634,25};
index = 6: return {25,634,25,478};
index = 7: return {634,25,478,24};
This isn't that hard of a concept, but I'm trying to do it with the .Skip() .Take()
extension methods. Is there an easier way to select the WindowSize
entries before an item instead of trying to find where the starting point is and then getting the next WindowSize
entries? I'm trying to think of an easier way to do this with linq than having all the bounds checking that is required with Skip()
and Take()
.
You could reverse the list and then do a Count() - index and then a Take() but that doesn't seem efficient.
I guess this would require minimal bound checking - just basic sanity checks. See if this works
IEnumerable<double> GetWindow(List<double> lst, int index, int windowSize) {
if(index >= lst.Length){
// Throw proper exception
}
return lst.Skip(index-windowSize).Take(Math.Min(index,windowSize));
}
If you only want to get one window, your accepted answer looks appropriate. But for iterating more than one window, I would go with something like this:
public static IEnumerable<IEnumerable<TSource>> Window<TSource>(
this IEnumerable<TSource> source, int size)
{
var q = new Queue<TSource>(size);
foreach (var value in source)
{
if (q.Count >= size)
q.Dequeue();
q.Enqueue(value);
yield return q;
}
}
精彩评论