Reputation: 526
I am currently working on a project where I need to sort entries of a list of tuples according to a certain scheme. For that purpose I wrote a simple IComparer:
private class OrderComparer : IComparer<Tuple<string, DateTime, string>>
{
public int Compare(Tuple<string, DateTime, string> x, Tuple<string, DateTime, string> y)
{
var yearX = x.Item1.Substring(x.Item1.Length - 2);
var yearY = y.Item1.Substring(y.Item1.Length - 2);
var monthX = x.Item1.Substring(x.Item1.Length - 4, 2);
var monthY = y.Item1.Substring(y.Item1.Length - 4, 2);
var numberX = x.Item1.Substring(1, x.Item1.Length - 5);
var numberY = y.Item1.Substring(1, y.Item1.Length - 5);
if (!yearX.Equals(yearY))
{
return Convert.ToInt32(yearX).CompareTo(Convert.ToInt32(yearY));
}
if (!monthX.Equals(monthY))
{
return Convert.ToInt32(monthX).CompareTo(Convert.ToInt32(monthY));
}
return Convert.ToInt32(numberX).CompareTo(Convert.ToInt32(numberY));
}
}
the reading of yearX/Y, monthX/Y and numberX/Y works correctly as found in a debugging session.
The problem I am now facing is that it sorts correctly after the year and month but not the number. I verified, that
return Convert.ToInt32(numberX).CompareTo(Convert.ToInt32(numberY));
returns the correct value (1 when numberX > numberY).
I call the sort method using the following code:
var dataList = data as IList<Tuple<string, DateTime, string>> ?? data.ToList();
dataList.ToList().Sort(new OrderComparer());
where data is an IEnumerable.
I am sorry for this rather simple question but I am completely stuck and I don't see any error in my implementation. Kind regards
Lukas EDIT: since sample data is needed. Here's the data the algorithm fails: B080114, B140114, B100114, B160114, B130114
this is the actual result after sorting
Upvotes: 0
Views: 363
Reputation: 27599
Your problem is in this line:
dataList.ToList().Sort(new OrderComparer())
the Sort
method as you know doesn't return the sorted version but operates on the original list. Here however the list it is sorting is not dataList
but dataList.ToList()
which is not the same item.
So it sorts dataList.ToList()
in place but since you have no reference to it it is thrown away and you are left with the unmodified dataList
instead.
The best fix would probably be to change the preceding line to:
var dataList = data.ToList();
So rather than checking if it is a suitable IList
and so on we are just doing a ToList()
to make sure we have a List so the next line can then be:
dataList.Sort(new OrderComparer());
This will now work on the correct list and hopefully thus do what you want.
Upvotes: 1
Reputation: 476584
It's hard to guess what the problem is since you don't provide sample data.
I assume you should replace
var numberX = x.Item1.Substring(1, x.Item1.Length - 5);
with:
var numberX = x.Item1.Substring(0, x.Item1.Length - 6);
(don't forget to modify the line for numberY
as well).
Since strings start with index 0
(and you probably only grab the last digit).
Although I would advice you to simply parse the string
to a DateTime
object (there is a builtin method for this, that will probably suffice), and then use the default comparable of the DateTime
object. This will improve speed as well since this method will parse string
objects on average O(n log n) times [and worst case O(n^2) times] instead of O(n) times
Upvotes: 2