背景
我创建了一个应该实现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
方法来实现这一目标?
答案 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
List
或Array
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查询方面实现了我想要的目标。