我有以下系列:
-3,-2,-1,0,1,2,3
我如何在单个order by
语句中按以下形式对它们进行排序:
负数首先按其(绝对值)排序,然后按正数排序。
-1,-2,-3,0,1,2,3
答案 0 :(得分:7)
组合排序,首先是符号,然后是绝对值:
list.OrderBy(x => Math.Sign(x)).ThenBy(x => Math.Abs(x));
或:
from x in list
orderby Math.Sign(x), Math.Abs(x)
select x;
这在概念上类似于SQL语句:
SELECT x
FROM list
ORDER BY SIGN(x), ABS(x)
在LINQ-to-Objects中,排序只执行一次,而不是两次。
警告:如果x == int.MinValue,Math.Abs(x)将失败。如果这个边缘情况很重要,那么你必须单独处理它。
答案 1 :(得分:6)
var numbers = new[] { -3, -2, -1, 0, 1, 2, 3 };
var customSorted = numbers.OrderBy(n => n < 0 ? int.MinValue - n : n);
这里的想法是将非负数与它们的值进行比较。并将负数与int.MinValue - n
的值-2147483648 - n
进行比较,因为n
为负数,我们的负数越高,结果的结果就越低。
当列表本身包含数字int.MinValue
时,它不起作用,因为它评估为0
本身等于0
。正如理查德所建议的那样,如果你需要全范围,可以使用long
来制作,但性能会因此受到轻微影响。
答案 2 :(得分:0)
尝试类似(VB.Net示例)
Orderby(Function(x) iif(x<0, Math.Abs(x), x*1000))
...如果值<&lt; 1000
答案 3 :(得分:0)
您可以在LINQ中表达它,但如果我在两年后阅读代码,我更愿意看到类似的内容:
list.OrderBy(i=>i, new NegativeThenPositiveByAscendingAbsoluteValueComparer());
您需要实现IComparer。