decimal[] array = new decimal[5]{80.23,60.20,88.01,77.00,20.45};
decimal TargetNumber = 70.40;
这里,最近的值是77.00,如何找到最接近的十进制数组的索引?
注意:它应该保持与我需要的最接近值的精确索引相同的顺序。在这里,指数比价值重要
答案 0 :(得分:2)
使用LINQ很长一段时间,如果找到完全匹配,你可以提前停止检查。 minIndex
保留索引,如果数组为空,则保留-1
。
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;
}
}
为了好玩,我制作了一个完全通用的版本,它要求你传递一个委托来计算距离因子,它还有一个可选参数来定义&#34;最小距离&#34;它需要停止检查更多的结果。
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;
}
}
答案 1 :(得分:2)
int nearestIndex = Array.IndexOf(array, array.OrderBy(number => Math.Abs(number - TargetNumber)).First());
答案 2 :(得分:1)
int index = array.Select((x,i) => new {Index=i, Distance = Math.Abs(TargetNumber - x)}).OrderBy(x => x.Distance).First().Index;
答案 3 :(得分:1)
您可以使用Enumerable.Aggregate
:
int nearestIndex = array
.Select((x, i) => new { Diff = Math.Abs(x - TargetNumber), Index = i })
.Aggregate((x, y) => x.Diff < y.Diff ? x : y)
.Index;
这只是不需要任何排序,而且只能在array
内迭代一次。
编辑:如果找到完全匹配的话,这个版本就会突破早期的 ,就像@ScottChamberlein建议的那样:
int exactMatch = 0;
var nearestIndex = array
.Select((x, i) => new { Diff = Math.Abs(x - TargetNumber), Index = i })
.TakeWhile(x => x.Diff != 0M || exactMatch++ == 0)
.Aggregate((x, y) => x.Diff < y.Diff ? x : y)
.Index;