Reputation: 932
I have got a list of Entity, which has got an enum.
public class Car
{
public int CarId { get; set; }
public string CarName { get; set; }
public CarCategory CarCategory { get; set; }
}
public enum CarCategory
{
None = 0,
kLowRange = 1,
kMidRange = 2,
kHighRange = 3
}
Now I have got a list of Cars, I would like to use Comparer and run it on the enum such that all the entity having CarCategory as kMidRange and kHighRange will be sorted to first in the list.
I have tried with the answer but havent found any luck.
Thanks.
UPDATE: I kinda have got the mistake I am doing. I was looking at
var sortedList = carList
.OrderBy(x => x.CarCategory,
new EnumComparer<CarCategory> {
CarCategory.kMidRange,
CarCategory.kHighRange});
But was getting only same values. I have to add .ToList() in order to get the result.
var sortedList = carList
.OrderBy(x => x.CarCategory,
new EnumComparer<CarCategory> {
CarCategory.kMidRange,
CarCategory.kHighRange})
.ToList();
Will give me the expected results. My mistake!
Upvotes: 19
Views: 53103
Reputation: 71
I want to complement Dmitry Bychenko answer
Problems
map
arraymap
array hasn't some numbers (when you add value to enum, but not add value to map
array)Than we get System.IndexOutOfRangeException
For example
public enum CarCategory
{
None = 0,
kLowRange = 30,
kMidRange = 2000,
kHighRange = 10,
kAnotherRangeCarCategory = 10000,
}
Than use Dmitry code
// desired order: None should be 3d, LowRange 4th, MidRange 1st, HighRange 2nd
int[] map = new[] {2000, 10, 0, 30};
var sortedList = carList
.OrderBy(x => map[(int) (x.CarCategory)])
.ToList();
Exception
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
Solution
var map = new Dictionary<CarCategory, int>() {
{ CarCategory.kMidRange, 0 },
{ CarCategory.kHighRange, 1 },
{ CarCategory.None, 2 },
{ CarCategory.kLowRange, 3 }
// without "kAnotherRangeCarCategory"
};
// Order by map, if map doesn't contains enum value, push item to end.
var sortedList = carList
.OrderBy(x => map.GetValueOrDefault(key: x.CarCategory, defaultValue: map.Count + 1))
.ToList();
This code work's correct and not throw System.IndexOutOfRangeException
P.S. You can also use strings instead enums. I talked about this in this answer
P.P.S I decided to create a small open source nuget library to solve this problem.
Installation
dotnet add package Kurnakov.PriorityOrder
Code example
using PriorityOrder;
var priorities = new List<CarCategory>()
{
CarCategory.kMidRange,
CarCategory.kHighRange,
CarCategory.None,
CarCategory.kLowRange,
// without "kAnotherRangeCarCategory"
};
var sortedList = carList
.OrderByPriority(x => x.CarCategory, priorities) // or with params[]
.ToList();
More details you can find here
Upvotes: 2
Reputation: 186668
enum
is effectively integer (int
in your case)
The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
see https://msdn.microsoft.com/en-us/library/sbbt4032.aspx for details.
Since CarCategory
implementation has the items in the desired order you can put just
var sortedList = carList
.OrderByDescending(x => (int) (x.CarCategory))
.ToList();
please, note Descending
: you want kHighRange
to be on the top. If you want an arbitrary order, e.g.
kMidRange, kHighRange, None, kLowRange
I suggest using mapping:
// desired order: None should be 3d, LowRange 4th, MidRange 1st, HighRange 2nd
int[] map = new[] {3, 4, 1, 2};
var sortedList = carList
.OrderBy(x => map[(int) (x.CarCategory)])
.ToList();
Upvotes: 50