AS3数学:数组中的最近邻居

时间:2012-04-04 15:34:06

标签: actionscript-3 math

所以,假设我有TT = 1200。我也有AA是一个包含1000个条目的数组,这些条目的数字条目范围为1000-2000,但不包含1200的条目。

找到最近邻居(最接近的值)的最快方法是什么,假设我们将其定格,因此它将匹配1201,而不是1199中的A

注意:这将在ENTER_FRAME上运行。

另请注意: A是静态的。

6 个答案:

答案 0 :(得分:3)

使用Vector.<int>代替Array也很快,并执行简单的for循环:

var vector:Vector.<int> = new <int>[ 0,1,2, /*....*/ 2000];

function seekNextLower( searchNumber:int ) : int {
    for (var i:int = vector.length-1; i >= 0; i--) {
        if (vector[i] <= searchNumber) return vector[i];
    }
}


function seekNextHigher( searchNumber:int ) : int {
    for (var i:int = 0; i < vector.length; i++) {
        if (vector[i] >= searchNumber) return vector[i];
    }
}

使用任何数组方法比迭代Vector.<int>更昂贵 - 它已针对这种操作进行了优化。

答案 1 :(得分:2)

如果您希望在每次ENTER_FRAME事件中运行此操作,您可能会受益于一些额外的优化。

如果在将条目写入阵列时跟踪这些条目,则无需对它们进行排序。

例如,你有一个数组,其中T是索引,它将有一个带有数组的对象,该数组包含保存该值的A数组的所有索引。你也可以把最接近的值的索引作为该对象的一部分,所以当你每帧检索一次时,你只需要访问那个值,而不是搜索。

当然,只有阅读比你写的更多,这才会有所帮助,因为重新创建对象非常昂贵,所以它实际上取决于使用。

您可能还想查看链接列表,对于某些操作,它们的速度要快一些(虽然排序速度较慢)

答案 2 :(得分:1)

您必须阅读每个值,因此复杂性将是线性的。这非常类似于在数组中找到最小的int。

var closestIndex:uint;
var closestDistance:uint = uint.MAX_VALUE;
var currentDistance:uint;
var arrayLength:uint = A.length;

for (var index:int = 0; index<arrayLength; index++)
{
  currentDistance = Math.abs(T - A[index]);
  if (currentDistance < closestDistance || 
        (currentDistance == closestDistance && A[index] > T)) //between two values with the same distance, prefers the one larger than T
  {
    closestDistance = currentDistance;
    closestIndex = index;
  }
}

return T[closestIndex];

答案 3 :(得分:1)

由于您的数组已经排序,您可以调整一个简单的二进制搜索(例如解释in this answer)来找到'pivot',其中左细分和递归步骤的右细分括起您的值'搜索'。

答案 4 :(得分:0)

只是一个想法我...排序A(因为它的静态你可以在你开始之前对它进行一次排序),然后猜测开始猜测的是什么(比如A是长度100,你想要1200 ,100 *(200/1000)= 20)所以从猜测开始猜测,然后如果A [guess]高于1200,检查A [guess-1]的值。如果它仍然更高,继续往下走,直到找到一个更高,一个更低。一旦找到确定更接近的东西。如果你的初步猜测太低,继续上升。

这不是很好,可能不是最好的表现,但它比检查每一个值要好得多,如果A在1000和2000之间均匀分布,它将会很好地工作。

祝你好运!

答案 5 :(得分:0)

public function nearestNumber(value:Number,list:Array):Number{
    var currentNumber:Number = list[0];
    for (var i:int = 0; i < list.length; i++) {
        if (Math.abs(value - list[i]) < Math.abs(value - currentNumber)){
            currentNumber = list[i];
        }
    }
    return currentNumber;
}