【问题标题】:How do I find the closest array element to an arbitrary (non-member) number?如何找到最接近任意(非成员)数字的数组元素?
【发布时间】:2010-11-16 11:39:51
【问题描述】:

看似相似的问题:“Finding closest number in an array”(Java 中)和“find nearest match to array of doubles”(实际上是地理问题)。

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

例如,使用以下数组:

  • 1.8
  • 2.4
  • 2.7
  • 3.1
  • 4.5

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

检测完全超出数组元素范围的值的奖励积分。例如,使用上面列出的数组,您的代码可能会确定 4.6 进入,但 5.9 退出。如果您想尝试这部分问题,具体情况掌握在您手中。

【问题讨论】:

标签: c# search approximate


【解决方案1】:

Array.BinarySearch,返回:

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

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

【讨论】:

    【解决方案2】:

    使用 LINQ 的一种方法如下:

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

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

    【讨论】:

    • @Steven - 谢谢。与您自己的方法非常相似;)
    • @Øyvind: 而你我们比我快 22 秒 :'(
    【解决方案3】:

    也许不是最快的解决方案,但肯定令人赏心悦目:

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

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

    【讨论】:

    • 请注意,他要求的是最接近值的索引,而不是最接近的值本身。
    • 这是一个不错的方法 :)
    • @Tom:当然没有接近马克答案的性能特征。这就是他得到我 +1 的原因。
    【解决方案4】:

    类似这样的:

    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]);
    

    【讨论】:

      【解决方案5】:
      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;
              }
          }
      }
      

      【讨论】:

      • 请提供一些评论,对您的贡献进行一些描述
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-07
      • 2016-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      相关资源
      最近更新 更多