【问题标题】:Sort list by calculate value按计算值排序列表
【发布时间】:2013-06-02 14:59:51
【问题描述】:

我有一个具有 x 和 y 值的 A 类列表:

class A
{
   public int X { get; set; }
   public int Y { get; set; }
}

我的清单:

List<A> MyList = GetListOfA();

我想通过计算 A 属性的值对列表进行排序。例如今天的美元汇率乘以 X。 如果我将使用 OrderBy 表达式,该方法将计算 x*log(x) 次。

我找到了一些方法来做到这一点,例如创建包含值和变量的内部类,将包含变量和计算值列表的匿名类型列表,通过计算值的键将其添加到排序字典等等

用简洁的语法来做这件事的最佳方法是什么?

【问题讨论】:

  • 乘以一个比率不会改变顺序(除非比率是非正数)。为什么不直接按原值排序而不用乘法?
  • 即使比率是非正数,这也只是颠倒排序顺序。

标签: c# .net sorting lambda


【解决方案1】:

如果我使用 OrderBy 表达式,该方法将计算 x*log(x) 次。

不,不会的。在 LINQ to Objects 中,OrderBy 将每个元素投影到其排序键一次,然后比较这些键。对于大小为n 的集合,将有n 对属性的访问,然后这些属性值之间的比较是O(n log n)。

所以基本上,您应该使用OrderBy 尽可能简单地编写代码 - 并相信它会相当高效。

【讨论】:

  • 绝对正确!不过,这种行为可以更清楚地记录下来。我认为原始海报可能将 LINQ OrderBy 情况与 ArrayList&lt;&gt; 上的 Sort 方法混淆了,您可以在其中指定 Comparison&lt;&gt; 委托。如示例myList.Sort((x, y) =&gt; ExpensiveMethod(x, y, otherArgs))。在这种情况下,如果List&lt;&gt; 的计数为n,那么委托肯定会被调用超过n 次。但情况不同。
  • @JeppeStigNielsen:我同意它肯定可以更清楚地记录......就像LINQ周围的各种事情一样。 (有些文档是完全错误的......)
【解决方案2】:

你可以使用IComparer&lt;T&gt;接口:

class A
{
    public int X { get; set; }
    public int Y { get; set; }
}

class AComparer : IComparer<A>
{
    public int Compare(A x, A y)
    {
        var fx = F(x);
        var fy = F(y);

        if (fx < fy) return -1;
        if (fx == fy) return 0;
        return 1;
    }

    double F(A a) // your calculation
    {
        return a.X * 1.2;
    }
}

在你的代码中:

var list = new List<A>();
// fill list
list = list.OrderBy(a => a, new AComparer()).ToList();

【讨论】:

    【解决方案3】:

    我建议您不要逐一更改列表,将其视为不可变的。

    保留此列表的副本,(如视图),所有操作都在其中发生。

    将所有内容封装在一个新类中。

    我会这样做的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      相关资源
      最近更新 更多