Sorry, I think we’re at cross purposes … I’m talking about integers, not strings.

Say I have an array of 50 integers n() that does not contain the value 100, but it does contain the value 98. When I say x = n.IndexofBestMatch(100), the function returns the index of value 98 in the array.

My code to do this is a “divide and conquer” binary tree search. I’ll just post it here and see if anyone would like to help make it better (or fix it if it’s wrong or badly done).

It calls one external method to clone an array if necessary, otherwise it’s self-contained.

```
Public Function IndexOfBestMatch(theArray() as integer, ValueToMatch as integer, arrayIsSorted as Boolean = false, favorHigherValue as Boolean = true, threshold as integer = -1) as integer
#pragma DisableBackgroundTasks
#pragma DisableBoundsChecking
// RETURN THE INDEX OF THE CLOSEST VALUE IN THE ARRAY
' It is assumed that the elements are unique.
' A value 0 <= x >= Ubound is always returned,
' unless a threshold is given, in which case -1 may be returned
' only when the best match does not meet the given threshold
if theArray.Ubound < 1 then return 0
dim test as integer = theArray.IndexOf( ValueToMatch )
if test > -1 then return test
' to do a binary search the array must be sorted
dim clonedArray(), correctIndexes() as integer
if not arrayIsSorted then
' The array isn't sorted, so we clone it and sort the clone.
' We keep an array of the unsorted indexes so that we can
' return the correct index, not the index of the sorted clone
clonedArray() = CloneArray( theArray() )
for j as integer = 0 to clonedArray.Ubound
correctIndexes.append j
next
clonedArray.sortwith( correctIndexes() )
else
' the array is already sorted,
' so the index to return matches its given order
clonedArray() = theArray()
for j as integer = 0 to clonedArray.Ubound
correctIndexes.append j
next
end if
' quick binary tree search, start in the middle
dim range as integer = clonedArray.Ubound+1
dim i as integer = ceil(range/2)
dim thisDiff, lastDiff, lastIndex as integer
while i > -1 and i <= clonedArray.Ubound
thisDiff = ValueToMatch - clonedArray( i )
' if the range is 1, then there is nowhere else to go, so exit
if range = 1 then exit while
lastDiff = thisDiff
lastIndex = i
range = ceil(range/2)
if thisDiff < 0 then
i = i - ceil(range/2)
else
i = i + ceil(range/2)
end if
wend
' case for arrays of size 1 or 2
if i > clonedArray.Ubound then return clonedArray.Ubound
if abs( thisDiff ) = abs( lastDiff ) then
// IT'S A TIE
' return the value favored, within bounds
if threshold = -1 then
if favorHigherValue then
if abs( thisDiff ) < abs( lastDiff ) then
return max( 0 , min( correctIndexes(i), clonedArray.Ubound ) )
else
return max( 0 , min( correctIndexes(lastIndex), clonedArray.Ubound ) )
end if
else
if abs( thisDiff ) < abs( lastDiff ) then
return max( 0 , min( correctIndexes(lastIndex), clonedArray.Ubound ) )
else
return max( 0 , min( correctIndexes(i), clonedArray.Ubound ) )
end if
end if
else
' best match did not meet threshold
return -1
end if
else
// NO TIE
' return the result, within bounds
if threshold = -1 then
if abs( thisDiff ) < abs( lastDiff ) then
return max( 0 , min( correctIndexes(i), clonedArray.Ubound ) )
else
return max( 0 , min( correctIndexes(lastIndex), clonedArray.Ubound ) )
end if
else
' best match did not meet threshold
return -1
end if
end if
End Function
```