假设我有一个对象列表:
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>
对象。这就是我试图找到进行这种选择性排序的最佳方式的原因。
答案 0 :(得分:7)
你可以试试这个 - 它会产生你期望的结果:
items.OrderBy(x.Order => x.Order == -1).ThenBy(x.Order => x.Order);
答案 1 :(得分:6)
正如迈克所提到的,在你的例子中,它会自动运行,但是我们想先得到所有-1个元素,然后按降序对剩余元素进行排序。这可以通过一个很好的技巧来完成。订购元素时可以使用多个键。第一个键可以是布尔值,对于所有-1值(因此它们将是第一个)将为false
,对于所有其他值将为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
一般情况下,当您需要处理某些元素时,尤其是在订购中,您只需要提供正确的订购密钥。
答案 2 :(得分:3)
如果按升序排序,-1应该已经位于列表的顶部,因为它是最小值。
然而,更一般地说,如果你仍然想对数据的子集应用不同的排序,我认为不会有更优雅的方式,因为这正是你正在做的事情,并且联合在逻辑上是准确的。你试图将两个单独的数据子集拉出来,对它们进行不同的排序,然后将它们合并在一起,这是我将要使用的东西之一。
答案 3 :(得分:1)
OrderBy(x => x.Order < 0 ? int.MaxValue : x.Order)
或者如果您需要按降序排列负值
OrderBy(x => x.Order < 0 ? (long)int.MaxValue - x.Order : (long)x.Order)
答案 4 :(得分:1)
这里也是一个自定义比较器,如果你想首先出现-1,但其余的是降序,但不知何故我发现它更优雅:)注意它是为int而制作的
class Comparer : IComparer<int>
{
public int Compare(int x, int y)
{
if (x == -1 || y == -1) return x - y;
return y - x;
}
}
答案 5 :(得分:0)
使用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());