列表视图滑动窗口

时间:2011-05-13 03:49:19

标签: c# linq

我有一个数字列表,我想选择一个特定大小的滑动窗口:

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};

这不是一个难以理解的概念,但我正在尝试使用.Skip() .Take()扩展方法。是否有更简单的方法在项目之前选择WindowSize条目,而不是尝试查找起点的位置,然后获取下一个WindowSize条目?我正在尝试使用linq更简单的方法来执行此操作,而不是使用Skip()Take()所需的所有边界检查。

您可以反转列表,然后执行Count() - index,然后执行Take(),但这看起来效率不高。

2 个答案:

答案 0 :(得分:3)

我想这需要最小限度检查 - 只需要进行基本的健全性检查。看看是否有效

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));
}

答案 1 :(得分:0)

如果您只想获得一个窗口,则您接受的答案看起来合适。 但是对于迭代多个窗口,我会选择这样的东西:

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;
    }
}