看似相似的问题:“Finding closest number in an array”(在Java中)和“find nearest match to array of doubles”(实际上是地理问题)。
我有一个(排序的)双打数组。给定一个任意数字(可能与其中一个数组元素完全匹配),如何返回最接近匹配的数字索引?
例如,使用以下数组:
查询2.5将返回索引为1,对应于2.4的值。
用于检测完全位于数组元素范围之外的值的加值点。例如,使用上面列出的数组,您的代码可能会决定4.6是否在,但5.9已经完成。如果您想尝试这部分问题,具体内容掌握在您手中。
答案 0 :(得分:11)
指定数组中指定值的索引(如果找到值)。如果未找到值且值小于数组中的一个或多个元素,则为负数,它是第一个元素的索引的按位补码,其大于值。如果找不到值并且value大于数组中的任何元素,则为负数,它是(最后一个元素的索引加1)的按位补码。
现在这不会让你100%的方式,因为你会知道这个数字小于或大于匹配,但它实际上只留下两个指数来检查。
答案 1 :(得分:6)
使用LINQ执行此操作的一种方法是:
public int GetClosestIndex( List<double> doublelist, double targetvalue )
{
return doublelist.IndexOf(doublelist.OrderBy(d => Math.Abs(d - targetvalue)).ElementAt(0));
}
它可能有一些性能问题,但如果列表不长,则不应该出现问题。此外,如果两个元素与目标值相等,它将返回那些元素的第一个索引。
答案 2 :(得分:3)
也许不是最快的解决方案,但肯定是令人愉快的眼睛:
double search;
double[] array;
var nearest = (
from value in array
orderby Math.Abs(value - search)
select value).First();
var index = array.IndexOf(nearest);
请注意,这绝对比二进制搜索算法慢,因为它需要处理数组中的每个元素,并且排序意味着构建这些项的哈希表。
答案 3 :(得分:0)
这样的事情:
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]);
答案 4 :(得分:0)
List<int> results;
int target = 0;
int nearestValue = 0;
if (results.Any(ab => ab == target)) {
nearestValue= results.FirstOrDefault<int>(i => i == target);
} else {
int greaterThanTarget = 0;
int lessThanTarget = 0;
if (results.Any(ab => ab > target) {
greaterThanTarget = results.Where<int>(i => i > target).Min();
}
if (results.Any(ab => ab < target)) {
lessThanTarget = results.Where<int>(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;
}
}
}