Find the largest dictionary <int, string> whose value is less than the search value
I have Dictionary<int,string>
with ascending keys:
var myDictionary = new Dictionary<int,string>
{
{750,"one"},
{1500,"two"},
{2500,"three"},
{5000,"four"},
{10000,"five"},
{25000,"six"}
}
I have var myValue = 3000.52
I need to find the largest myDictionary
key that is less than my value. In this case, I need to return 2500.
I tried:
foreach (var key in myDictionary.Keys.Where(key => key <= myValue))
{
}
But, as you might expect, all lower values also coincide.
How do I find the largest key that is less than my search value?
source to share
You can create List<int>
from the keys a dictionary. I would keep this list if you need to search for it often. Then you can use List.BinarySearch
to find the closest key:
int key = 3000;
var keys = new List<int>(myDictionary.Keys);
// keys.Sort(); if it was not already sorted
var index = keys.BinarySearch(key);
if (index >= 0)
{
// dictionary contains this key
}
else
{
int nextSmaller = ~index - 1;
string valueOfNextSmaller = myDictionary[keys[nextSmaller]]; // three
}
BinarySearch
returns the zero index of the element in the sorted List<T>
one if the element is found; otherwise, a negative number that is the bit's complement to the index of the next element greater than the element, or, if there is no larger element, the bit's complement to Count.
source to share
Giorgos answer is the best way to work with Dictionary
, but it will be slow because it will search the entire keyspace. If you want something fast, the C5 Collections library has a lot of features not found in .NET. You can do it:
TreeDictionary<K,V> dict;
var last = dict.RangeTo(myValue).Backwards().First();
which will run in O (log n), much more efficient as your vocabulary grows.
source to share