【问题标题】:Linq - advanced .OrderByLinq - 高级 .OrderBy
【发布时间】:2011-06-22 20:17:37
【问题描述】:
Foo().OrderBy(x=> x.Name)

如果我希望以这种方式对集合进行排序,但只有一个具有 Id == 的元素(比如 314)应该始终位于开头,无论其名称如何。

【问题讨论】:

    标签: c# linq c#-4.0


    【解决方案1】:

    你可以分两轮排序:

    Foo().OrderBy(x => x.Id == 314 ? 0 : 1).ThenBy(x => x.Name)
    

    也许这更简单(假设 boolean false 在 boolean true 之前运行)

    Foo().OrderBy(x => x.Id != 314).ThenBy(x => x.Name)
    

    【讨论】:

    • 布尔假排序在真之前。 ILSpy 显示 Boolean.CompareTo 如果值相等则返回 0,如果 this 为假则返回 -1,否则返回 1。
    【解决方案2】:

    我个人会在客户端处理这个问题,但如果你想要一种 LINQ 方式,那么我可能会避免使用Concat - 这将是一个更复杂的查询。我会去:

    int id = 314;
    var data = Foo().OrderBy(x => x.Id == id ? 0 : 1).ThenBy(x => x.Name)
    

    【讨论】:

      【解决方案3】:

      尝试使用Union

      var foo = Foo();
      foo.Where(x => x.id == 314).Union(foo.OrderBy(x => x.Name));
      

      【讨论】:

      • 根据 MSDN(参见上面的链接),这比涉及Concat 的任何解决方案都更好,因为Concat 允许重复。
      • Single 返回一个对象 - 你不能在上面调用 Union
      • 这会调用 Foo() 两次,这并不总是一个好主意。
      • 联合可以改变结果。这个问题并没有说来源确实/不包含重复项。为了安全起见,我会亲自使用 Concat。好吧,实际上我不会 - 但在 Union 和 Concat 之间,我会使用 Concat。
      • @Platinum - 不,我是说如果原始数据有重复,那么我们当然应该保留它们。联盟将(非常确定地)删除它们。 Concat 不会(非常确定地)不会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 2020-06-10
      • 2011-11-21
      相关资源
      最近更新 更多