Aug 28, 2007
Posted On : 08/28/2007 at 12:34 PM | Posted By : Remote Synthesis
Related Categories:
ColdFusion
Here's a simple but useful UDF for handling arrays in ColdFusion. I was working on something today where I would create an array that happened to have a number of undefined elements contained within. What I wanted was to have all the undefined elements removed. ColdFusion 8 did add the ArrayIsDefined() function, but I needed this to work on 7 as well, so I copied a bit from
Ray Camden's
ArrayDefined UDF. CFLib actually had an
ArrayCompact UDF that has a similar goal, except that it will only work for arrays with simple values, while this will work for arrays with any type of value.
Now, before anyone criticizes the use of duplicate(), I will make it known that the original version of this function simply tried to modify the reference to the original array and returned nothing. Theoretically, this should have worked since arrays are passed by reference, but it didn't and I am not quite sure why. When I dumped the argument in the function itself after it ran, you would see the array was properly modified, but when I viewed the original it still showed the empty values. If anyone can explain this, I would love to hear it (p.s. for this, I was testing on 7).
<cffunction name="arrayRemoveEmpty" access="public" description="removes empty array elements" output="false" returntype="array">
<cfargument name="theArray" required="true" type="array" />
<cfset var i = 0 />
<cfset var newArray = duplicate(arguments.theArray) />
<cfloop from="#arrayLen(newArray)#" to="1" index="i" step="-1">
<cftry>
<cfset newArray[i] />
<cfcatch type="coldfusion.runtime.UndefinedElementException">
<cfset arrayDeleteAt(newArray,i) />
</cfcatch>
<cfcatch type="coldfusion.runtime.CfJspPage$ArrayBoundException">
<cfset arrayDeleteAt(newArray,i) />
</cfcatch>
</cftry>
</cfloop>
<cfreturn newArray />
</cffunction>
I have to ask the obvious question though: why not refactor the code building the array to not append empty elements? ;-)
Posted By
Brian Kotek / Posted on 08/28/2007 at 12:29 PM
How come you are catching specific error types? What kind of error would get thrown that would cause you NOT to want to delete the array item?
Posted By
Ben Nadel / Posted on 08/28/2007 at 12:30 PM
@Brian - Well, that is easier said than done. In this case, the elements in the array are navigation nodes that have a user controlled sort order. I place the elements in that position to easily maintain the order but the CMS system it relies on does not enforce that each position actually contain a node.
Anyway, that is one use for it but I think there are occasions when a function of this sort comes in handy.
@Ben - yeah, you are right. I thought of that since those specific messages are from Ray's original function but ended up just leaving it alone. It would be cleaner as just an "any" and really wouldn't have any impact on the function itself.
Posted By Brian Rinaldi / Posted on 08/28/2007 at 12:36 PM
Ben, it's not a question of not wanting to delete the item if a unexpected type of error is thrown, but a question of wanting to know if an unexpected error is thrown. The defined exception types are expected. If something else goes wrong, it is not expected, and that means you probably want to know about it.
Posted By
Brian Kotek / Posted on 08/28/2007 at 12:38 PM
@Brian - I would normally agree with you, but we are talking about one line of code in the try block which I think fairly well negates the possibility of some other type of error. Still, since there is no negative impact to the more explicit version above I am inclined to just leave it alone and people can decide for themselves :)
Posted By Brian Rinaldi / Posted on 08/28/2007 at 12:43 PM
@Brian,
I can understand the theory behind it, but given that the only CFTry statement is:
<cfset newArray[i] />
Anything that would throw an error at this point, would probably ALSO throw an error in ArrayDeleteAt(). Sure, at that point, you are throwing two exceptions as opposed to one... but even that is theory - cause if the argument type is Array, then really the only legit exception would be an undefined element type (or course several Java types might evaluate to Array but not support Array functionality - but is that worth the explicit error type handling?)
... all to say, I think a straight-up CFCatch would suffice :)
Posted By
Ben Nadel / Posted on 08/28/2007 at 12:46 PM
A catch-all cfcatch would probably suffice, I agree. I was just pointing out the rationale of explicitly typing the caught exceptions. I'd probably err on the side of being overly specific. You just never know. Right about the time you start thinking "there is no way this can ever happen", it does. ;-)
Posted By
Brian Kotek / Posted on 08/28/2007 at 12:52 PM
@Brian, I know what you're talking about; like, a few months ago I was all thinking "There is no way ColdFusion can get better than this!" and then BLAM! CF8 beta comes out :)
Posted By
Ben Nadel / Posted on 08/29/2007 at 4:44 AM
You know, it would probably have been faster to do a:
temp = newArray.get(i);
if(NOT isDefined("temp"))
{
ArrayDeleteAt(newArray, i)
}
Because exception handling tends to be pretty sloooooow ;o)
I like the post tho' ;o)
Posted By
Mark Mandel / Posted on 08/29/2007 at 2:52 PM