如何为实现IEnumerable <ienumerable <t>&gt; </ienumerable <t>的类实现GetEnumerator方法

时间:2012-12-05 13:58:25

标签: c# linq ienumerable

背景 我创建了一个应该实现TimeSeries<T>接口的通用IEnumerable<IEnumerable<T>>类:

public interface ITimeSeries<T> : IEnumerable<IEnumerable<T>> 
{
    T[,] DataMatrix { get; }  

    DateTime[] DateTime { get; }

    string[] Variables { get; }
}

public class TimeSeries<T> : ITimeSeries<T>
{
    public IEnumerator<IEnumerable<T>> GetEnumerator()
    {...}

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

TimeSeries<T>类被“内部”实现为矩阵数据结构,每列代表一个不同的变量,每一行代表一个观察。还有一个额外的DateTime[]数组代表时间轴。

首先,我希望能够通过带有TimeSeries<T>循环的变量迭代foreach变量,并通过所有对特定变量的观察(内部foreach)进行迭代循环),但IEnumerable接口实现的实际原因是通过IEnumerable接口获取LINQ提供的所有功能,前提是我可以某种方式确保每个观察的DateTime关联保持不变。

所以对于这个问题: 我应该如何实现GetEnumerator方法来实现这一目标?

2 个答案:

答案 0 :(得分:2)

最简单的方法就是遍历行并返回每行的值。我假设你以行主要顺序存储,其中第一个维度是行,第二个维度是列。只需按下列主要顺序的r和c:

public IEnumerator<IEnumerable<T>> GetEnumerator()
{
    int rows = DataMatrix.GetLength(0);
    int cols = DataMatrix.GetLength(1);

     for(int r = 0; r < rows; r++)
     {
        T[] row = new T[cols]();

        for(int c = 0; c < cols; c++)
        {
            row[c] = DataMatrix[r,c];
        }
        yield return row;
    }
}

如果您想避免复制,可以将其实现为List ListArray Array s({{1}而不是T[][])。

答案 1 :(得分:0)

我决定添加一个包装每个值的结构,并添加DateTime标记和变量名称属性,GetEnumerator方法生成一列包装值:

    public struct TSItem<T>
    {
        public string Variable { get; private set; }
        public DateTime Date { get; private set; }
        public T Value { get; private set; }
    }

    public IEnumerator<IEnumerable<TSItem<T>>> GetEnumerator()
    {
        int rows = DataMatrix.GetLength(0);
        int cols = DataMatrix.GetLength(1);

        for (int c = 0; c < cols; c++)
        {
            var col = new List<TSItem<T>>();

            for (int r = 0; r < rows; c++)
            {
                col.Add(new TSItem<T>(this.Variables[c], this.DateTime[r], 
                                DataMatrix[r, c]));
            }
            yield return col;
        }
    }

这可能不是最高性能的解决方案,但在LINQ查询方面实现了我想要的目标。