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; } // ============================================================================ //