基本上,我有一个对象集合,每个对象都实现类型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...
}

09-26 23:20