LINQ order by null column其中order是升序,null应该是last

sf.*_*sf. 123 c# linq sorting

我正在尝试按价格对产品列表进行排序.

结果集需要按列从低到高的价格列出产品LowestPrice.但是,此列可以为空.

我可以按降序对列表进行排序,如下所示:

var products = from p in _context.Products
   where p.ProductTypeId == 1
   orderby p.LowestPrice.HasValue descending
   orderby p.LowestPrice descending
   select p;

// returns:    102, 101, 100, null, null
Run Code Online (Sandbox Code Playgroud)

但是我无法弄清楚如何按升序排序.

// i'd like: 100, 101, 102, null, null
Run Code Online (Sandbox Code Playgroud)

Dav*_*haw 148

尝试将两列放在相同的顺序中.

orderby p.LowestPrice.HasValue descending, p.LowestPrice
Run Code Online (Sandbox Code Playgroud)

否则每个orderby是对集合的单独操作,每次重新排序它.

这应该先命名一个带值的那个,然后是"那个"值的顺序.

  • 常见的错误,人们对Lamda语法做同样的事情 - 使用.OrderBy两次而不是.ThenBy. (19认同)
  • 干杯.这么简单,我觉得自己像个白痴:P (5认同)
  • **这有效**对顶部有值的字段和底部有空字段的字段进行排序我使用了这个:`orderby p.LowestPrice == null, p.LowestPrice升序`希望对某人有所帮助。 (3认同)

jas*_*son 80

理解LINQ查询语法以及如何将其转换为LINQ方法调用确实很有帮助.

事实证明

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending
               orderby p.LowestPrice descending
               select p;
Run Code Online (Sandbox Code Playgroud)

将由编译器翻译为

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .OrderByDescending(p => p.LowestPrice)
                       .Select(p => p);
Run Code Online (Sandbox Code Playgroud)

这显然不是你想要的.这通过排序Product.LowestPrice.HasValuedescending订单,然后通过重新排序的整个集合Product.LowestPricedescending顺序.

你想要的是什么

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .ThenBy(p => p.LowestPrice)
                       .Select(p => p);
Run Code Online (Sandbox Code Playgroud)

您可以使用查询语法获取

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending,
                       p.LowestPrice
               select p;
Run Code Online (Sandbox Code Playgroud)

有关从查询语法到方法调用的转换的详细信息,请参阅语言规范.认真.阅读.

  • +1或只是...不要编写LINQ查询语法:)尽管如此,还是很好的解释 (4认同)

小智 14

在这种情况下,我有另一种选择.我的列表是objList,我必须订购,但空值必须在最后.我的决定:

var newList = objList.Where(m=>m.Column != null)
                     .OrderBy(m => m.Column)
                     .Concat(objList.where(m=>m.Column == null));
Run Code Online (Sandbox Code Playgroud)


Jai*_*der 14

字符串值的解决方案非常奇怪:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString) 
Run Code Online (Sandbox Code Playgroud)

有效的唯一原因是因为第一个表达式OrderBy(),排序bool值:true/ false.false结果首先跟随true结果(nullables)并按ThenBy()字母顺序对非空值进行排序.

所以,我更喜欢做一些比较可读的东西:

.OrderBy(f => f.SomeString ?? "z")
Run Code Online (Sandbox Code Playgroud)

如果SomeString为null,则将替换为"z",然后按字母顺序对所有内容进行排序.

注意:这不是一个终极解决方案,因为"z"首先比z值更像zebra.

更新 2016年9月6日 - 关于@jornhd评论,它确实是一个很好的解决方案,但它仍然有点复杂,所以我建议将它包装在Extension类中,例如:

public static class MyExtensions
{
    public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, string> keySelector)
    {
        return list.OrderBy(v => keySelector(v) != null ? 0 : 1).ThenBy(keySelector);
    }
}
Run Code Online (Sandbox Code Playgroud)

简单地使用它:

var sortedList = list.NullableOrderBy(f => f.SomeString);
Run Code Online (Sandbox Code Playgroud)

  • 我认为这更具可读性,没有讨厌的常量: .OrderBy(f =&gt; f.SomeString != null ? 0 : 1).ThenBy(f =&gt; f.SomeString) (2认同)

use*_*er1 9

我试图找到一个LINQ解决方案,但无法解决这里的答案.

我的最终答案是:

.OrderByDescending(p => p.LowestPrice.HasValue).ThenBy(p => p.LowestPrice)
Run Code Online (Sandbox Code Playgroud)


小智 7

我的决定:

Array = _context.Products.OrderByDescending(p => p.Val ?? float.MinValue)
Run Code Online (Sandbox Code Playgroud)


Aar*_*nLS 7

这是我想出来的,因为我使用扩展方法,而且我的项目是一个字符串,因此没有.HasValue:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)
Run Code Online (Sandbox Code Playgroud)

这适用于内存中的LINQ 2对象.我没有用EF或任何DB ORM测试它.