旋转数组集合

发布于 2024-09-18 19:51:43 字数 1345 浏览 11 评论 0原文

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

Basically, I have a collection of objects each implement a member of Type IValueCollection.

public interface IValueCollection : IEnumerable<decimal>
{
    decimal this[int index] { get; set; }
}

MeasurementCollection.Values is of type IValueCollection.

With the logic below I want to pivot a collection of IValueCollection and wrote the extension method below.

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

should do
{{1,2,3}{4,5,6}{7,8,9}} results in {{1,4,7},{2,5,8},{3,6,9}}
However I think there is some nicer, slimmer and more readable expression to do this
can somebody point me in the right direction?

edit
info about underlying classes

interface IValueCollection : IEnumerable<decimal>
class MeasurementCollection : ICollection<IMeasurement>

interface IMeasurement 
{
    IMeasurementTemplate Template { get; }        
    ......
}

interface IMeasurementTemplate
{
    .....
    MeasurementFrequency Frequency { get; }    
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清君侧 2024-09-25 19:51:43

我个人会强制提前评估您的集合,并将其用作数组。现在,每次调用 ElementAt 时,您都会再次评估 IEnumerable,导致大量重复搜索。

通过强制它提前计算为数组,可以简化整个过程。类似于:

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 作为输入。然后你可以这样做:

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

I would, personally, force the evaluation of your collection in advance, and use it as an array. Right now, each time you call ElementAt, you're going to evaluate the IEnumerable<T> again, causing a lot of repeated searching.

By forcing it to evaluate to an array in advance, you simplify the entire process. Something like:

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

If you control MeasurementValueCollection, I would add a constructor which takes an IEnumerable<decimal> as input, as well. You could then do:

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...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文