[英]How to Implement GetEnumerator method for class that implements IEnumerable<IEnumerable<T>>
BACKGROUND: I created a generic TimeSeries<T>
class that should implement the IEnumerable<IEnumerable<T>>
interface: 背景:我创建了一个通用的
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();
}
}
The TimeSeries<T>
class is 'internally' implemented as a matrix data structure with each column representing a different variable and each row an observation. TimeSeries<T>
类是“内部”实现为矩阵数据结构,每列代表一个不同的变量,每一行代表一个观察。 There is also an additional DateTime[]
array that represents the time axis. 还有一个表示时间轴的附加
DateTime[]
数组。
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. 作为一个开始,我希望能够通过变量使用
foreach
循环遍历TimeSeries<T>
变量,并通过所有对特定变量的观察(使用内部foreach
循环),但是IEnumerable接口实现的实际原因是通过IEnumerable
接口获取LINQ提供的所有功能,前提是我可以某种方式确保每个观察的DateTime关联保持不变。
So for the question: How should I go about to implement the GetEnumerator
method to achieve this? 所以对于这个问题:我应该如何实现
GetEnumerator
方法来实现这一目标?
Simplest way is just to loop through the rows and return the values of each row. 最简单的方法是循环遍历行并返回每行的值。 I'm assuming you're storing in row-major order where the first dimension is the row and the second is the column.
我假设你以行主要顺序存储,其中第一个维度是行,第二个维度是列。 Just flip r and c below for column-major order:
只需按下列主要顺序的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;
}
}
If you want to avoid making a copy, you could implement it as either a List
of List
s or an Array
of Array
s (a T[][]
instead of a T[,]
). 如果要避免复制,可以将其实现为
List
of List
或Array
of Array
( T[][]
而不是T[,]
)。
I've decided to add a struct which wraps each value and adds the DateTime stamp and Variable name properties and the GetEnumerator method yields a column of wrapped values: 我决定添加一个包装每个值的结构,并添加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;
}
}
This is probably not the most performant solution, but achieves what I want in terms of LINQ queries. 这可能不是最高性能的解决方案,但在LINQ查询方面实现了我想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.