比方说,我有对象的列表:
var items = new {
new { Order = 0 },
new { Order = 1 },
new { Order = -1 },
new { Order = 3 },
new { Order = 2 },
new { Order = -1 }
};
我需要订购它,以便与Order > -1
项目是由升序排序列表的顶部,并与Order == -1
其余项目被跟了上去。
是否有这样做比使用Conact()
和Where()
条款的更优雅的方式:
var orderedItems = items.Where(x => x.Order > -1).OrderBy(x => x.Order)
.Conact(items.Where(x => x.Order == -1);
所以这对该列表进行排序后,将如下所示:
var items = new {
new { Order = 0 },
new { Order = 1 },
new { Order = 2 },
new { Order = 3 },
new { Order = -1 },
new { Order = -1 }
};
此外,在实际场景中items
名单已经是一个复杂的IQueryable<T>
对象。这就是为什么我试图找到做这样的选择排序的最优化的方式。
你可以试试这个 - 它产生你所期望的结果:
items.OrderBy(x.Order => x.Order == -1).ThenBy(x.Order => x.Order);
正如迈克提到的,在你的榜样,它会自动工作,而是说,我们想先得到所有-1元素,并以降序排序,然后剩余的元素。这可以通过使用一个好的技巧来完成。订货元素时,您可以使用多个键。第一密钥可以是一个布尔值,这将是false
所有-1的值(因此它们将是第一个)和用于true
所有其他值(因此它们不会被重新排序)。第二个键可以是您要订购剩余的元素不管。例如:
var nums = new int[] { -1, 4, 2, 3, -1, 4, 7 };
var q = from n in nums
orderby n != -1, n descending
select n;
它首先会产生针对n != -1
是false
,然后所有元素使用n descending
排序,这样你会得到所有的值:
-1, -1, 7, 4, 4, 3, 2
当你需要处理尤其是在订货一些元素这个工作一般 - 你只需要提供正确的排序键。
如果您订购的升序,-1应该已经在列表的顶部,因为它是最小的值。
然而,更一般地,如果你仍然想不同的排序应用到数据的子集,我不认为会有一个更优雅的方式,因为这是你在做什么和工会在逻辑上是正确的。你想提取数据的两个不同的子集了,他们不同的排序,然后将它们合并在一起,这是对的事情我是工会要用于之一。
另外这里,如果你想自定义比较-1到第一次出现,但其余的要降,但不知何故,我觉得它更优雅:)注意它是整数制作
class Comparer : IComparer<int>
{
public int Compare(int x, int y)
{
if (x == -1 || y == -1) return x - y;
return y - x;
}
}
OrderBy(x => x.Order < 0 ? int.MaxValue : x.Order)
或者,如果你需要按降序排序负值
OrderBy(x => x.Order < 0 ? (long)int.MaxValue - x.Order : (long)x.Order)
使用custom comparer来定义你想要的顺序。
public class MyComparer : IComparer<int>
{
public int Compare(int a, int b)
{
if ((a < 0) && (b >= 0))
{
return 1;
}
if ((a >= 0) && (b < 0))
{
return -1;
}
return int.Compare(a, b);
}
}
然后,你可以这样做:
var orderedItems = items.OrderBy(x => x.Order, new MyComparer());