如何找到最接近任意(非成员)数字的数组元素?

看似相似的问题:“ 在数组中查找最接近的数字 ”(在Java中)和“ 找到与双打数组最接近的匹配 ”(实际上是地理问题)。

我有一个(排序的)双打数组。 给定一个任意数字(可能是也可能不是其中一个数组元素的完全匹配),如何返回最接近匹配的数字的索引?

例如,使用以下数组:

  • 1.8
  • 2.4
  • 2.7
  • 3.1
  • 4.5

查询2.5将返回索引为1,对应于2.4的值。

用于检测完全在数组元素范围之外的值的加分点。 例如,使用上面列出的数组,您的代码可能会决定4.6是否在,但是5.9已经完成。 如果您想尝试这部分问题,具体内容掌握在您手中。

Array.BinarySearch ,返回:

如果找到值,则指定数组中指定值的索引。 如果未找到值且值小于数组中的一个或多个元素,则为负数,它是第一个元素的索引的按位补码,其大于值。 如果找不到值且值大于数组中的任何元素,则为负数,它是(最后一个元素的索引加1)的按位补码。

现在这不会让你100%的方式,因为你会知道这个数字小于或大于匹配,但它实际上只留下两个索引来检查。

使用LINQ执行此操作的一种方法是这样的:

 public int GetClosestIndex( List doublelist, double targetvalue ) { return doublelist.IndexOf(doublelist.OrderBy(d => Math.Abs(d - targetvalue)).ElementAt(0)); } 

它可能有一些性能问题,但如果列表不长,则不应该造成问题。 此外,如果两个元素与目标值相等,它将返回那些元素的第一个索引。

也许不是最快的解决方案,但肯定是令人愉快的眼睛:

 double search; double[] array; var nearest = ( from value in array orderby Math.Abs(value - search) select value).First(); var index = array.IndexOf(nearest); 

请注意,这绝对比二进制搜索算法慢,因为它需要处理数组中的每个元素,并且排序意味着构建这些项的哈希表。

像这样的东西:

 double[] values = new double[] { 1.8, 2.4, 2.7, 3.1, 4.5 }; double difference = double.PositiveInfinity; int index = -1; double input = 2.5; for (int i = 0; i < values.Length; i++) { double currentDifference = Math.Abs(values[i] - input); if (currentDifference < difference) { difference = currentDifference; index = i; } // Stop searching when we've encountered a value larger // than the inpt because the values array is sorted. if (values[i] > input) break; } Console.WriteLine("Found index: {0} value {1}", index, values[index]); 
 List results; int target = 0; int nearestValue = 0; if (results.Any(ab => ab == target)) { nearestValue= results.FirstOrDefault(i => i == target); } else { int greaterThanTarget = 0; int lessThanTarget = 0; if (results.Any(ab => ab > target) { greaterThanTarget = results.Where(i => i > target).Min(); } if (results.Any(ab => ab < target)) { lessThanTarget = results.Where(i => i < target).Max(); } if (lessThanTarget == 0 ) { nearestValue= greaterThanTarget; } else if (greaterThanTarget == 0) { nearestValue = lessThanTarget; } else { if (target - lessThanTarget < greaterThanTarget - target) { nearestValue = lessThanTarget; } else { nearestValue = greaterThanTarget; } } }