
Find several nearest numbers in C# Dictionary
Recently I had a small task, trying to solve a specific problem. Maybe there exist better methods to solve the problem, though as I am new to C#, I’ve tried to solve it with “primitive” method.
I had a dictionary (it will be somehow similar with List or Array), which had keys/pairs like this:
[0] => 13 [1] => 18 [2] => 24 [3] => 35 [4] => 42 [5] => 54 [6] => 66 [7] => 74
(this dictionary was being sorted either in Ascending or Descending)
Then the program was provided with a random number (by provider), let’s say number 21 and the program had to find nearest 2 greater values and 2 less values – in this case answer should be: 13,18(below) and 24,35(above).
However, for them, who want to do a quick home-task and dont want to rewrite from ground, this snippet might be useful (I think the code is self-explaining). At first, I determined if dictionary is ascending or descending, then manually counted every “greater” and “less” occurrences and removed all other keys :
Dictionary<int,double> MyD = Dictionary<int,double>();
MyD[0] = 13;
MyD[1] = 18;
MyD[2] = 24;
MyD[3] = 35;
MyD[4] = 42;
MyD[5] = 54;
MyD[6] = 66;
MyD[7] = 74;
double Target_value = 21;
int how_many_values_to_find = 2;
Dictionary<int,double> MyD_New =FindNearestValuesInDict(MyD, Target_value,how_many_values_to_find); // =====> returns 13,18 and 24,35
Actual code of method is:
// ============================== find nearest values ================== //
public Dictionary<int, double> FindNearestValuesInDict(Dictionary<int,double> MyDict, double Target_value, int how_many_values_to_find){
bool Is_Ascending= DictIsAscendingOrDescending(MyDict);
int KeysAmount= MyDict.Keys.Count();
int greater_count=0, lower_count=0;
int idx_pos=0, idx_neg=0;
Dictionary <int, double> MyDictFinal= new Dictionary<int,double>(MyDict);
for(int i=0; i < KeysAmount; i++){
idx_pos = Is_Ascending ? i : KeysAmount-1-i;
idx_neg = Is_Ascending ? KeysAmount-1-i : i;
//remove all "grater than" occurences
if(MyDict.Keys.ElementAtOrDefault(idx_pos) != null){
dynamic keyNm_pos= MyDict.Keys.ElementAt(idx_pos);
if(ContainsValue(MyDict,keyNm_pos)) {
if (MyDict[keyNm_pos] > Target_value) {
greater_count ++;
if( greater_count >how_many_values_to_find) {
MyDictFinal.Remove(keyNm_pos);
}
}
}
}
//remove all "lower than" occurences
if(MyDict.Keys.ElementAtOrDefault(idx_neg) != null){
dynamic keyNm_neg= MyDict.Keys.ElementAt(idx_neg);
if(ContainsValue(MyDict,keyNm_neg)) {
if (MyDict[keyNm_neg] < Target_value) {
lower_count++;
if( lower_count>how_many_values_to_find) {
MyDictFinal.Remove(keyNm_neg);
}
}
}
}
}
return MyDictFinal;
}
// helper function to above
public bool DictIsAscendingOrDescending(Dictionary<int,double> MyDict){
// Note: some keys might not exist at all //
int KeysAmount= MyDict.Keys.Count();
double last_obtained_value=double.NaN;
//find if ascending or descending
for(int i=0; i< KeysAmount; i++){
dynamic keyNm= MyDict.Keys.ElementAt(i);
if(ContainsValue(MyDict,keyNm)) {
if (!double.IsNaN(last_obtained_value)){
return MyDict[keyNm]>last_obtained_value;
}
last_obtained_value = MyDict[keyNm];
}
}
return false;
}
// ============================================================================ //