我正在尝试按价格对产品列表进行排序.
结果集需要按列从低到高的价格列出产品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是对集合的单独操作,每次重新排序它.
这应该先命名一个带值的那个,然后是"那个"值的顺序.
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.HasValue在descending订单,然后通过重新排序的整个集合Product.LowestPrice的descending顺序.
你想要的是什么
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)
有关从查询语法到方法调用的转换的详细信息,请参阅语言规范.认真.阅读.
小智 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)
我试图找到一个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)
这是我想出来的,因为我使用扩展方法,而且我的项目是一个字符串,因此没有.HasValue:
.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)
Run Code Online (Sandbox Code Playgroud)
这适用于内存中的LINQ 2对象.我没有用EF或任何DB ORM测试它.