Find several nearest(closest) values in C# Dictionary/List/Array

keys and value in an array or dictionary

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

Leave a Reply

Your email address will not be published. Required fields are marked *