One nice thing about doing it the long way over using LINQ is you can stop checking early if you find a exact match. minIndex
holds the index or will hold -1
if the array was empty.
decimal minDistance = 0; //0 is fine here it is never read, it is just to make the compiler happy.
int minIndex = -1;
for(int i = 0; i < array.Length; i++)
{
var distance = Math.Abs(TargetNumber - array[i]);
if(minIndex == -1 || distance < minDistance)
{
minDistance = distance;
minIndex = i;
//Optional, stop testing if we find a exact match.
if(minDistance == 0)
break;
}
}
Just for fun I made a totally generic version, it requires you to pass in a delegate to calculate the distance factor, also it has a optional parameter to define the "minimum distance" it needs to be to stop checking for more results.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
decimal[] array = new decimal[5]{80.23M,80.40M,80.80M,80.00M,20.45M};
decimal TargetNumber = 70.40M;
var result = FindClosestIndex(TargetNumber, array, (target, element) => Math.Abs(target - element)); //Optionally add in a "(distance) => distance == 0" at the end to enable early termination.
Console.WriteLine(result);
}
public static int FindClosestIndex<T,U>(T target, IEnumerable<T> elements, Func<T,T,U> distanceCalculator, Func<U, bool> earlyTermination = null) where U : IComparable<U>
{
U minDistance = default(U);
int minIndex = -1;
using(var enumerator = elements.GetEnumerator())
for(int i = 0; enumerator.MoveNext(); i++)
{
var distance = distanceCalculator(enumerator.Current, target);
if(minIndex == -1 || minDistance.CompareTo(distance) > 0)
{
minDistance = distance;
minIndex = i;
}
if(earlyTermination != null && earlyTermination(minDistance))
break;
}
return minIndex;
}
}