Homam
Homam

Reputation: 23841

Custom order by, is it possible?

I have the following collection:

-3, -2, -1, 0, 1, 2, 3

How can I in a single order by statement sort them in the following form:

The negative numbers are sorted first by their (absolute value) then the positive numbers.

-1, -2, -3, 0, 1, 2, 3

Upvotes: 2

Views: 2411

Answers (4)

Stephen Chung
Stephen Chung

Reputation: 14605

Combination sorting, first by the sign, then by the absolute value:

list.OrderBy(x => Math.Sign(x)).ThenBy(x => Math.Abs(x));

or:

from x in list
orderby Math.Sign(x), Math.Abs(x)
select x;

This is conceptually similar to the SQL statement:

SELECT x
FROM list
ORDER BY SIGN(x), ABS(x)

In LINQ-to-Objects, the sort is performed only once, not twice.

WARNING: Math.Abs(x) will fail if x == int.MinValue. If this marginal case is important, then you have to handle it separately.

Upvotes: 7

Lasse Espeholt
Lasse Espeholt

Reputation: 17782

var numbers = new[] { -3, -2, -1, 0, 1, 2, 3 };

var customSorted = numbers.OrderBy(n => n < 0 ? int.MinValue - n : n);

The idea here is to compare non-negative numbers by the value they have. And compare negative numbers with the value int.MinValue - n which is -2147483648 - n and because n is negative, the higher negative number we, the lower negative result the outcome will be.

It doesn't work when the list itself contains the number int.MinValue because this evaluates to 0 which would be equal to 0 itself. As Richard propose it could be made with long´s if you need the full range but the performance will be slightly impaired by this.

Upvotes: 6

James L
James L

Reputation: 16864

You could express it in LINQ, but if I were reading the code two years later, I'd prefer to see something like:

list.OrderBy(i=>i, new NegativeThenPositiveByAscendingAbsoluteValueComparer());

You will need to implement IComparer.

Upvotes: 0

Tobias Schittkowski
Tobias Schittkowski

Reputation: 2251

Try something like (VB.Net example)

Orderby(Function(x) iif(x<0, Math.Abs(x), x*1000))

...if the values are <1000

Upvotes: 1

Related Questions