如何在VBA中编写“Application.Match”的JavaScript代码? – 用于数值插值函数

我想在JavaScript中编写一个INTERPOLATION函数,以便能够使用Google表格而不是Excel出于多种目的。 在Excel中,我有用VBA编写的这个用户定义函数:

Function interpolate_1D(xreq As Single, x As Range, y As Range) As Single ' If we have variable y that is a function of x and have two ranges, x and y that give the values 'of y for particular values of x, we may need to find the value of y for a value of x not 'given in the table. 'For example, we may have power curve data for a wind turbine that gives the power output of a wind turbine 'for integer values of the wind speed. To find the output power at any other speed we could 'use this function, using as arguments: 'xreq: wind speed for which we wish to know the output power 'x: range containing the known wind speeds in ascending order 'y: range containing the known wind turbine powers Dim pointer As Integer Dim x0 As Single, y0 As Single, x1 As Single, y1 As Single pointer = Application.Match(xreq, x, 1) x0 = x(pointer) x1 = x(pointer + 1) y0 = y(pointer) y1 = y(pointer + 1) interpolate_1D = y0 + (xreq - x0) * (y1 - y0) / (x1 - x0) End Function 

我可能从某个地方复制了这个,比如Billo的“科学家和工程师的Excel”一书。 它工作得很好,就像我写的2D版本一样。

我相当新的JavaScript,现在我不能看到如何让它做Application.Match(xreq,x,1)行的等价物,它通过已知x值的范围,查找最小值的位置小于search值xreq。 一旦我有了这个位置,我可以做所有的事情。

有任何想法吗?

你可能不需要。 您可能可以使用数组.IndexOf方法:

http://www.w3schools.com/jsref/jsref_indexof_array.asp

 var fruits = ["Banana", "Orange", "Apple", "Mango"]; var a = fruits.indexOf("Apple"); 

a的结果将是:2

是否有可能以另一种语言重新创build优化的 Match工作表函数需要更详细的底层代码知识,目前我无法提供。

否则,如果没有看到更多的你在做什么,我会说试图重buildMatch函数 – 虽然它会慢一些 – 就像在数组上powershell迭代一样简单(如果你testing的话,这会更快一个数组,而不是范围对象)。

我修改了Tim Williams的testing函数来比较几种方法。 在这些testing中,将Contains函数转换为数组之后,会对范围.Value进行testing。 我testingMatch函数针对数组,和对范围对象,并testingWorksheetFunction.Match对范围。

 Sub Tester() Application.ScreenUpdating = False Dim i As Long, B, T Dim Arr As Variant Dim rng As Range Set rng = Range("A1:A10000") rng.Formula = "=""value_""&" & "RandBetween(1,1000)" Range("A100000").Value = "Value_50" T = Timer Arr = Application.Transpose(rng.Value) For i = 1 To 10000 B = Contains(Arr, "Value_50") Next i Debug.Print "Contains (array)" & vbTab & Timer - T T = Timer Arr = Application.Transpose(rng.Value) For i = 1 To 10000 B = Application.Match("Value_50", Arr, False) Next i Debug.Print "Match (array)" & vbTab & Timer - T T = Timer For i = 1 To 10000 B = Application.Match("Value_50", rng, False) Next i Debug.Print "Match (range)" & vbTab & Timer - T T = Timer On Error Resume Next For i = 1 To 10000 B = Application.WorksheetFunction.Match("Value_50", rng, False) Next i On Error GoTo 0 Debug.Print "WorksheetFunction.Match (range)" & vbTab & Timer - T Application.ScreenUpdating = True End Sub 

当在内存中的数组上执行时,观察到Contains自定义函数比Match快,但是在工作表上的Range对象上执行时, Application.MatchApplication.WorksheetFunction.Match函数都比其中任何一个都快得多。

 Contains (array) 18.90625 Match (array) 43.25 Match (range) 0.2304688 WorksheetFunction.Match (range) 0.1914063 

感谢@CharlesWilliams对此计时testing的意见/讨论并澄清了一些相关的事情。

您可以使用此处给出的函数,并在循环中添加您自己的逻辑来查找您正在查找的值。

@所有,

最后,我得到了这个工作:

 function interpolate (xreq,knowndata){ var data = knowndata; for (var i = 0; i < data.length-1; i++) { if (xreq >=data[i][0] & xreq <data[i+1][0]) {break} } return data[i][1] + (data[i+1][1] - data[i][1]) / ( data[i+1][0] - data[i][0]) * (xreq - data[i][0]); } 

它需要error handling,但做我想要的工作。 “knowndata”是包含已知x和y数据的2列范围,其中x按升序排列。 “xreq”是我们想要估计y的最佳值的新x值。 这不使用MATCH的等价物,但至less它给了我一个线性插值函数来完成这项工作,所以现在我可以将几个Excel电子表格移植到Google表格中。

感谢所有您的意见 – 读起来很有趣。