【问题标题】:index of closest a number in array, closest to x, that cannot be larger than x数组中最接近 x 的数字的索引,不能大于 x
【发布时间】:2016-08-05 12:31:00
【问题描述】:

如何编写一个函数,该函数接受一个整数数组和一个整数 x,并返回数组中最接近 x 参数且不大于 x 的整数的索引。如果都高于 x,则函数将返回负数。假设数组中的两个或多个数字不能相同。

【问题讨论】:

  • 如果有多个结果怎么办?
  • 不会有多个解决方案。它说返回最近的一个,并假设数组中没有重复项。
  • 不会有。数组中的所有数字都不一样
  • 取决于功能对性能的重要性。我可能只是对其进行排序,然后进行二进制搜索。不过,我会远离 linq - 根据我的经验,它的性能可怕

标签: c# arrays search


【解决方案1】:

假设数字是唯一的,你可以使用

public static int GetClosestIndex(int[] arr, int value)
{
    var result = arr.Where(x => x < value).OrderByDescending(x => x);
    return result.Any() ? Array.IndexOf(arr, result.FirstOrDefault()) : -1;
}

更新:(针对 Zastai)

这是一种性能更好的方法

public static int GetClosestIndex(int[] arr, int value)
{
    int result = -1;
    for (int i = 0; i < arr.Length; i++)
    {
        if (arr[i] < value)
        {
            if (result == -1 || arr[i] > arr[result])
            {
                result = i;
            }
        }
    }
    return result;
}

【讨论】:

  • 虽然功能正确且代码相当优雅,但几乎可以肯定它的性能会很差。
【解决方案2】:

我会去的

public static class StackOverflow {

public static int IndexOfValueClosestTo<T>(this IList<T> list, T x) where T : IComparable<T> {
  var closestValue = default(T);
  var closestIndex = -1;
  var idx = -1;
  foreach (var v in list) {
    ++idx;
    if (v.CompareTo(x) < 0 && (closestIndex == -1 || closestValue.CompareTo(v) < 0)) {
      closestIndex = idx;
      closestValue = v;
    }
  }
  return closestIndex;
}

}

它仍然非常易读,适用于数组、列表……并处理整数、双精度数…… 也是一种扩展方式,所以StackOverflow.IndexOfValueClosestTo(mylist, myvalue)mylist.IndexOfValueClosestTo(myvalue)都可以使用。

LINQPad 中包含一百万个元素的数组的一些基本基准测试也表明,这比基于 LINQ 的答案快 30 倍(100 次迭代需要约 1.05 秒,而 LINQ 版本需要约 37 秒)。

但是,为了获得绝对最佳性能,请使用专门用于 int 数组的版本:

public static int IndexOfValueClosestTo(this int[] list, int x) {
  var closestValue = 0;
  var closestIndex = -1;
  var idx = -1;
  foreach (var v in list) {
    ++idx;
    if (v < x && (closestIndex == -1 || closestValue < v)) {
      closestIndex = idx;
      closestValue = v;
    }
  }
  return closestIndex;
}

它在约 0.33 秒内运行 100 次迭代,因此它的速度大约是上述通用版本的 3 倍。请注意,您可以将两者都定义为重载,因此您仍然有一个有效的实现,例如双精度列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多