Copy link to clipboard
Copied
Hi,
Is it possible to check if an Array is defined and in the same CFIF statement check to make sure it's numeric?
Something like:
<cfif ArrayIsDefined(F,2) AND IsNumeric>
Taking it one step further I need to make sure the value is between 1 and 99.
ArrayIsDefined and IsNumeric and GT 0 and LT 100....
Suggestions?
Thanks in advance.
Gary
Copy link to clipboard
Copied
<!--- 'gte' assumes that the value of myArray[2] may include 1 or 99. If not, use 'gt' instead --->
<cfif isdefined("variables.myArray") and arrayIsDefined(myArray, 2) and isNumeric(myArray[2]) and (myArray[2]-1)*(99-myArray[2]) gte 0>
</cfif>
or
<cfif structKeyExists(variables, "myArray") and arrayIsDefined(myArray, 2) and isNumeric(myArray[2]) and (myArray[2]-1)*(99-myArray[2]) gte 0>
</cfif>
Copy link to clipboard
Copied
Hi Gary,
Sure, you can just use the AND operator to add multiple conditions to the cfif statement:
<cfif ArrayIsDefined(F,2) AND isNumeric(f[2]) AND f[2] GTE 1 AND f[2] LTE 99>
The conditions are evaluated using short circuit logic, so if ArrayIsDefined(F,2) is false, then isNumeric(f[2]) is never executed.
Pete Freitag
Copy link to clipboard
Copied
Pete, Thanks... I was struggling with the [ ]. Stupid mistake - I was doing #F[2]#
Copy link to clipboard
Copied
<cfset allAreNumeric_1to99 = true />
<cfswitch expression="#arrayIsDefined(myArray,1)#"><!--- checks if there is at least one item in array --->
<cfcase value="yes">
<cfloop from="1" to="#ArrayLen(myArray)#" index="idx">
<cfif val(myArray[idx]) gte 1 AND val(myArray[idx]) lte 99>
<!--- within parameters, do nothing --->
<cfelse>
<cfset allAreNumeric_1to99 = false />
<cfbreak />
</cfif>
</cfloop>
</cfcase>
<cfdefaultcase>It's not an array! EPIC FAIL!</cfdefaultcase>
</cfswitch>
<cfoutput>#allAreNumeric_1to99#</cfoutput>
HTH,
^ _ ^
Copy link to clipboard
Copied
Wolfshade... That made my novice brain hurt. Now I have to create a test page to play with that code and teach myself what the heck it does. Thanks!!!!
Copy link to clipboard
Copied
It's very simple, actually... it's just that the switch/case might make it appear difficult. But I prefer switch/case over if/else.
First, I'm setting a variable called allIsNumeric_1to99 to true.
Next, I'm using a switch/case to check if the array is defined; this will also check to make sure that there is at least one item in the array.
If it's an array, then loop through it (iterate it) checking that the value of the current position is between 1 and 99. If it is less than one or higher than 99, it sets that first variable to false and breaks out of the loop. (HINT: Using val() on a string like "a" will produce a value of zero.)
If it's NOT an array (cfdefaultcase), then it displays "It's not an array! EPIC FAIL!".
After the switch/case, it outputs the value of #allAreNumeric_1to99#. Either true or false.
HTH,
^ _ ^
Copy link to clipboard
Copied
Interesting... So switch / case is a true / false way to do if/else. Seems like that could be very useful for many different reasons.
Copy link to clipboard
Copied
ghanna1 wrote
So switch / case is a true / false way to do if/else.
Actually,
switch
case 1
case 2
case 3
..., etc.,
is usually a better alternative to the, often, mind-boggling
if
else if
else if
else if
...,etc.
There is another point.
ghanna1 wrote
I need to make sure the value is between 1 and 99
"The value" suggests one element of the array (that is, at one index). One <cfif> line should therefore suffice.
Copy link to clipboard
Copied
ghanna1 wrote
Interesting... So switch / case is a true / false way to do if/else. Seems like that could be very useful for many different reasons.
As I understand it (and if someone can prove that my assertion is incorrect, I'm always open to learning new things), an if/else if/else statement will parse each and every instance, but will actually use only the code that matches the condition. This is problematic for two reasons: 1) it uses CPU that is unnecessary, and 2) if any of the code in any instance (used or not used) uses something that isn't defined, it will throw an error. (I know it works that way in ColdFusion; I've experienced it.)
A switch/case statement, however, will go through each case value until it finds the condition, then executes only the code within. After that, it breaks out of the switch to continue processing what is after it. So it's more efficient than an if/else if/else statement. If there is a variable that isn't defined being used in a case that isn't processed, it won't matter. CPU doesn't see/use/parse it.
Now, I recently learned about something called a "dispatch table". It's a lot more code, but supposedly _slightly_ more efficient than a switch/case, because it's a data structure that contains properties, and there is no conditional comparison involved - the property is drilled to directly, without comparing to any value or boolean. (UPDATE: Okay, that does sound odd, because you have to use the value of the property name in order to access said property, but I think you get the gist of what I'm typing. Accessing a property is faster than comparing values.)
V/r,
^ _ ^
UPDATE: Come to think of it, the information I gleaned was from over a decade ago, so things may have changed. But I have not yet read or heard anything contrary to my above.
Copy link to clipboard
Copied
WolfShade, are you saying the following code will error out on line 5 because an undefined variable is being evaluated even if the first condition is true? This does not happen for me. I tried the code in https://trycf.com/ and https://cffiddle.org/ and I do not get an error.
<cfscript>
variables.definedVar = 1;
if (variables.definedVar == 1)
writeOutput('variables.definedVar is 1');
else if (variables.undefinedVar == 2 )
writeOutput('should never get here');
</cfscript>
Copy link to clipboard
Copied
The code you provided _should_ error due to variables.undefinedVar not existing, and maybe either Java or CF has improved to correct that. But years ago your sample code would have errored. I'm thinking around CF 7 or 8, I experienced this issue in a IF/ELSE conditional that was corrected with a switch/case. I could not param the variable, don't remember why (that was years ago.)
V/r,
^ _ ^
Copy link to clipboard
Copied
WolfShade wrote
... I'm using a switch/case to check if the array is defined; this will also check to make sure that there is at least one item in the array.
If it's an array, then loop through it (iterate it) checking that the value of the current position is between 1 and 99. If it is less than one or higher than 99, it sets that first variable to false and breaks out of the loop. (HINT: Using val() on a string like "a" will produce a value of zero.)
If it's NOT an array (cfdefaultcase), then it displays "It's not an array! EPIC FAIL!".
WolfShade, there is a counterexample:
<cfset testVar=[]>
<!--- alternatively --->
<cfset testVar=arrayNew(1)>
TestVar contains no item but is defined and is an array.
Copy link to clipboard
Copied
Actually, I could have done that with myArray.map(), but if you're a novice that would most likely make your brain hurt.
V/r,
^ _ ^
Copy link to clipboard
Copied
Noticing the part about 1 and 99, I updated my post.
Copy link to clipboard
Copied
ghanna1 wrote
Is it possible to check if an Array is defined and in the same CFIF statement check...
That calls for something like
isdefined("myArray"), isdefined("variables.myArray") or structKeyExists(variables,"myArray")
Copy link to clipboard
Copied
Every time I post something simple here I walk away learning so many new things! I'm four months into cleaning up craptastic code written in 2008 by a former employee and each pass over the code I'm finding more efficient and more secure ways of doing things.
Copy link to clipboard
Copied
There are a lot of differences between code today and decade-old code. CF has come a long way, for sure. The ESAPI, alone, is a big difference.
V/r,
^ _ ^