Вы можете решить проблему, дважды используя адаптированный бинарный поиск на Keys
, чтобы найти индексы, которые связывали интересующий диапазон в коллекции Keys
.
Поскольку IList
не предлагайте бинарные средства поиска, которые вам нужно написать самостоятельно. К счастью, есть также возможность украсть готовые реализации из . Как выполнить бинарный поиск в IList .
Вот адаптированная версия, чтобы найти нижнюю границу:
public static int LowerBound(this IList list, T value, IComparer comparer = null)
{
if (list == null)
throw new ArgumentNullException("list");
comparer = comparer ?? Comparer.Default;
int lower = 0, upper = list.Count - 1;
while (lower <= upper)
{
int middle = lower + (upper - lower) / 2;
int comparisonResult = comparer.Compare(value, list[middle]);
// slightly adapted here
if (comparisonResult <= 0)
upper = middle - 1;
else
lower = middle + 1;
}
return lower;
}
Чтобы реализовать UpperBound
, просто измените
if (comparisonResult <= 0)
на
if (comparisonResult < 0)
. Теперь это тривиально:
var low = set.Keys.LowerBound(value);
var high = set.Keys.UpperBound(value);
// These extra comparisons are required because the adapted binary search
// does not tell us if it actually found the needle. They could be rolled
// into the methods themselves, but this would require another out parameter.
if (set.Keys[low] != value) ++low;
if (set.Keys[high] != value) --high;
if (low <= high) /* remove keys in the range [low, high] */