Трудно реализовать это эффективно с SortedDictionary<TKey, TValue>
, поскольку оно реализовано в виде двоичного дерева поиска, которое не раскрывает предшественников или преемников.
Конечно, вы можете просто перечислять каждую KeyValuePair, пока не найдете «известный» ключ. С небольшим количеством LINQ это будет выглядеть (при условии, что ключ определенно существует, а не первый):
SortedDictionary<int, int> dictionary = ...
int knownKey = ...
var previousKvp = dictionary.TakeWhile(kvp => kvp.Key != knownKey)
.Last();
Если эти предположения не верны, вы можете сделать:
var maybePreviousKvp = dictionary.TakeWhile(kvp => kvp.Key != knownKey)
.Cast<KeyValuePair<int, int>?>()
.LastOrDefault();
(Убедитесь, что maybePreviousKvp != null
, чтобы убедиться, что предыдущая KeyValuePair была успешно извлечена.)
Но это не будет эффективным вообще.
Если это возможно, рассмотрите возможность использования SortedList<TKey, TValue>
(очевидно, это может быть невозможно, если вы не можете использовать его медленные вставки и удаления). Эта коллекция поддерживает эффективный поиск ключей и значений по упорядоченному индексу , поскольку она реализована в виде расширяемого массива. Тогда ваш запрос станет таким простым:
SortedList<int, int> dictionary = ...
int knownKey = ...
int indexOfPrevious = dictionary.IndexOfKey(knownKey) - 1;
// if "known" key exists and isn't the first key
if(indexOfPrevious >= 0)
{
// Wrap these in a KeyValuePair if necessary
int previousKey = dictionary.Keys[indexOfPrevious];
int previousValue = dictionary.Values[indexOfPrevious];
}
IndexOfKey
запускает двоичный поиск по списку ключей, который выполняется за O(log n)
времени. Все остальное должно выполняться в постоянное время, то есть вся операция должна выполняться в логарифмическом времени.
В противном случае вам придется реализовать себя / найти коллекцию BST, которая раскрывает предшественников / преемников.