基本上,我有一个对象集合,每个对象都实现类型IValueCollection
的成员。
public interface IValueCollection : IEnumerable<decimal>
{
decimal this[int index] { get; set; }
}
MeasurementCollection.Values
的类型为IValueCollection
。使用下面的逻辑,我想透视
IValueCollection
的集合并在下面编写扩展方法。public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
int s = (int)items.First().Template.Frequency;
int c = items.Count;
for (int n = 0; n < s; n++)
{
IValueCollection v = new MeasurementValueCollection(c);
for (int m = 0; m < c; m++)
v[m] = items.ElementAt(m).Values[n];
yield return v;
}
}
}
应该做
{{1,2,3}{4,5,6}{7,8,9}}
导致{{1,4,7},{2,5,8},{3,6,9}}
但是我认为有一些更好,更苗条,更易读的表达方式可以做到这一点
有人可以指出我正确的方向吗?
编辑
有关基础类的信息
interface IValueCollection : IEnumerable<decimal>
class MeasurementCollection : ICollection<IMeasurement>
interface IMeasurement
{
IMeasurementTemplate Template { get; }
......
}
interface IMeasurementTemplate
{
.....
MeasurementFrequency Frequency { get; }
}
最佳答案
我个人将提前对您的收藏进行评估,并将其用作数组。现在,每次调用ElementAt时,您将再次评估IEnumerable<T>
,从而导致大量重复搜索。
通过强制它预先评估一个数组,可以简化整个过程。就像是:
public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
int elementLength = (int)items.First().Template.Frequency;
var itemArray = items.ToArray();
for (int n = 0; n < itemArray.Length; n++)
{
IValueCollection v = new MeasurementValueCollection(elementLength);
for (int m = 0; m < elementLength; m++)
{
v[m] = itemArray[m].Values[n];
}
yield return v;
}
}
else
yield break; // Handle the case where IsQuantized() returns false...
}
如果您控制
MeasurementValueCollection
,我还将添加一个接受IEnumerable<decimal>
作为输入的构造函数。然后,您可以执行以下操作:public static IEnumerable<IValueCollection> PivotValues(this MeasurementCollection items)
{
if(items.IsQuantized())
{
var elements = Enumerable.Range(0, (int)items.First().Template.Frequency);
var itemArray = items.ToArray();
foreach(var element in elements)
yield return new MeasurementValueCollection(
itemArray.Select(
(item,index) => itemArray[index].Value[element]
)
);
}
else
yield break; // Handle the case where IsQuantized() returns false...
}