Given:
List<DateTime> descOrderedDates;
And a datetime:
DateTime fromDate;
I can easily count the number of items where the date is greater than fromDate
as follows:
var count = descOrderedDates.Count(c=> c > fromDate);
However I'm struggling to implement this as a BinarySearch
:
var ix = descOrderedDates.BinarySearch(fromDate, new CompareDates());
private class CompareDates : IComparer<DateTime>
{
public int Compare(DateTime compareDate, DateTime fromDate)
{
if (fromDate > compareDate) return 1;
return 0;
}
}
This keeps returning 1
in a test case where fromDate
is less than the smallest date in the list. I'm struggling to wrap my head around IComparer
, can anyone tell me what I'm doing wrong?
CodePudding user response:
Your comparer returns 1 in case of fromDate > compareDate
, but it should also return -1 in the opposite case, and 0 only if they're equal. And do you need a custom comparer at all? I believe for dates the default comparison will work fine.
CodePudding user response:
You are supposed to return either a negative value, a positive value, or 0 in Compare
, depending on whether the parameters are greater than, less than, or equal to each other, as the documentation says. (So your implementation of not returning negative values at all is incorrect.)
You can do that by explicitly writing out the three cases and comparing the dates with <
and >
, but DateTime
has the CompareTo
method (as it implements IComparable
), so you can just use that instead:
public int Compare(DateTime date1, DateTime date2)
=> date2.CompareTo(date1);
Note that the order of the two dates are reversed when we call CompareTo
, to achieve the descending order for the Comparer
that we are implementing.
If you want to find the first index of the list with a date that is less than fromDate
, you also need to do some checking on ix
:
int firstIndexLessThanFromDate;
if (ix < 0) {
// applying bitwise not gives you where the element should be inserted
// i.e. the index of the next smallest element
firstIndexLessThanFromDate = ~ix;
} else {
firstIndexLessThanFromDate = ix 1;
}