Reputation: 73
hi there i have an list of float
List<float> distance = new List<float>();
distance.Add(66.2F);
distance.Add(69.9F);
distance.Add(70.2F);
distance.Add(70.3F);
distance.Add(70.6F);
distance.Add(71.4F);
distance.Add(71.6F);
i have a extension method which get nearest number from this array
public static class extenstions
{
public static float ClosestTo(this IEnumerable<float> collection, float target)
{
var closest = float.MaxValue;
var minDifference = float.MaxValue;
foreach (var element in collection)
{
var difference = Math.Abs((long)element - target);
if (minDifference > difference)
{
minDifference = (int)difference;
closest = element;
}
}
return closest;
}
}
float closest = distance.ClosestTo(70F); now if i want to find nearest of number 70 it will return 70.2 what i want is to modify this function to return less closest 69.9 instead of higher value 70.2. can you help?
Upvotes: 0
Views: 3489
Reputation: 292465
Using Linq:
public static float ClosestTo(this IEnumerable<float> collection, float target)
{
return collection.OrderBy(x => Math.Abs(target - x)).First();
}
Or, using the MinBy
extension method from Linq.Extras:
public static float ClosestTo(this IEnumerable<float> collection, float target)
{
return collection.MinBy(x => Math.Abs(target - x));
}
It's better than using OrderBy
because it runs in O(n)
instead of O(n log n)
.
EDIT: if two numbers are equally close to the target and you want the greater of the two, you can do this:
public static float ClosestTo(this IEnumerable<float> collection, float target)
{
return collection
.OrderBy(x => Math.Abs(target - x))
.ThenByDescending(x => x)
.First();
}
Upvotes: 4
Reputation: 593
Probably when u cast value to long u lose number after coma 70,2 -> 70 and 69,9 -> 69 and 70 is closest to 70 than 69
If u want to take closest from left or right use this :
public static float ClosestTo(this IEnumerable<float> collection, float target)
{
float a = collection.Where(x => x >= target).OrderBy(x => x - target).First();
float b = collection.Where(x => x < target).OrderBy(x => Math.Abs(target - x)).First();
return a.Equals(b) ? a : Math.Min(a, b);
}
where a
is right and b
is left ( if u wanna left change return a.Equals(b) ? a : Math.Min(a, b);
to return a.Equals(b) ? b : Math.Min(a, b);
Upvotes: 2