Fast way to test if a value is between several ranges
Posted: 03 Jul 2012 13:08
The usual way to check if a given variable contain anyone of several possible values is by trying to delete the variable from the list of values; if the result is the same, the variable is not in the list:However, if the possible values may include a range, the test can not be achieved directly:The usual way to achieve this test is via a FOR loop that get each value or range from the list and perform individual tests, but this method is slow.
The fastest way to do this test is by defining an array with individual elements for each one of the possible values, including one element for each value in a range, so the testing is immediate:However, if the number of testing values is large...... this method requires a large amount of environment space in the testing variables, but what is worst is that the time involved just in creating the array may be much larger than the FOR iterative method's.
There is another approach to solve this problem using an aritmethic expression. For example, we may check if a variable is 10 or 45 with this command:If the variable have anyone of these two values the test is zero. To check if the variable is into a range, we may use this method:
Previous expression requires a small provision in case the variable is equal to anyone of the limits (to manage the division by zero). This way, to test a variable vs. several individual values or ranges, just assemble the appropiate aritmethic expression combining all intermediate values with multiplications. If the final result is zero, the variable is equal to one of the individual values or is into one range.
Antonio
Code: Select all
set values=10,25,45,90,120,180
if "!values:%variable%=!" neq "!values!" echo The variable IS in the list
Code: Select all
set values=10,25-35,45,90-110,120-150,180
The fastest way to do this test is by defining an array with individual elements for each one of the possible values, including one element for each value in a range, so the testing is immediate:
Code: Select all
if defined testValue[%variable%] echo The variable IS in the list
Code: Select all
set values=10-1500,2000-25000, 32000
There is another approach to solve this problem using an aritmethic expression. For example, we may check if a variable is 10 or 45 with this command:
Code: Select all
set /A test=(10-variable)*(45-variable)
Code: Select all
set /A (lowerLimit-variable) is negative or zero if variable >= lowerLimit
set /A (variable-UpperLimit) is negative or zero if variable <= upperLimit, so
set /A (lowLimit-var)*(var-UpLimit) is positive or zero if variable is in range,
negative otherwise, and
set /A aux=(Low-var)*(var-Up), test=(aux-1)/aux set test=0 if variable is in range,
test=1 otherwise
Code: Select all
@echo off
setlocal EnableDelayedExpansion
set /P "values=Enter the list of values or ranges: "
call :makeTestingExpr values
:next
set n=
set /P "n=Enter a number to test: "
if not defined n goto :EOF
set /A r=%expr% 2> NUL
if %r% equ 0 echo Number IS in values
goto next
:makeTestingExpr valuesVar
rem Assemble the testing expression for the variable given in %1
set expr=1
for %%b in (!%1!) do (
for /F "tokens=1,2 delims=-" %%c in ("%%b") do (
if "%%d" equ "" (
rem Individual value: multiply previous expr by direct subtract
set "expr=!expr!*(%%c-n^)"
) else (
rem Range value pair: use range expression at this point, then continue
set "expr=!expr!,a=r,r=0,b=(%%c-n^)*(n-%%d),r=(b-1)/b*a"
)
)
)
exit /B
Antonio