3

BACKGROUND: I created a generic TimeSeries<T> class that should implement the IEnumerable<IEnumerable<T>> interface:

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

The TimeSeries<T> class is 'internally' implemented as a matrix data structure with each column representing a different variable and each row an observation. There is also an additional DateTime[] array that represents the time axis.

As a start I would like to be able to iterate through the TimeSeries<T> variable by variable with a foreach loop and also through all observations for a specific variable (with an inner foreach loop), but the actual reason for the IEnumerable interface implementation is to get all the features provided by LINQ through the IEnumerable interface, provided that I can somehow ensure that the DateTime association of each observation stays intact.

So for the question: How should I go about to implement the GetEnumerator method to achieve this?

4

2 回答 2

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

如果您想避免复制,您可以将其实现为 a Listof Lists 或 an Arrayof Arrays(aT[][]而不是 a T[,])。

于 2012-12-05T14:14:00.737 回答
0

我决定添加一个结构,它包装每个值并添加 DateTime stamp 和 Variable name 属性,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 查询方面实现了我想要的。

于 2012-12-05T17:45:23.613 回答