CFLOOP over arrays as collections

March 19, 2012 · By Christian Ready · 1 Comment

The default looping approach one has is to either loop from 1 to the last element of an array or to use the <cfloop array=”#theArray#” index=“element”> notation. Next to the fact that the naming is misleading, both approaches have a disadvantage. So let's have a look:

<cfset aArray = ["January","February","March","April","May","June","July",
"August","September","October","November","December"]>
<cfset aArray[14] = "Out of bounds">

<cfloop from="1" to="#arrayLen(aArray)#" index="i">
   <cfoutput>#i#: #aArray[i]#<br></cfoutput>
</cfloop>

The above code loops through a regular array until the last element of the array. But of course the 13th element will cause a runtime error since there is no Element at position 13. So you would need to do something like:

<cfloop from="1" to="#arrayLen(aArray)#" index="i">
   <cfif arrayIndexExists(aArray, i)>
      <cfoutput>#i#: #aArray[i]#<br></cfoutput>
   </cfif>
</cfloop>

So you could use the other notation (for arrays) which looks like this:

<cfloop array="#aArray#" index="i">
   <cfoutput>#i#: #aArray[i]#<br></cfoutput>
</cfloop>

This of course throws an error since the introduction of this behaviour is misleading. Unfortunately the index does NOT contain the index but the element of the array. So aArray[i] above would throw an error. You would have to use this approach:

<cfset iCnt = 0>
<cfloop array="#aArray#" index="sElem">
   <cfoutput>#++iCnt#: #sElem#<br></cfoutput>
</cfloop>

But this is ugly right? Or what happens if you have the following array:

<cfset aArray = []>
<cfset aArray[2] = "February">
<cfset aArray[4] = "April">
<cfset aArray[6] = "June">
<cfset aArray[8] = "August">
<cfset aArray[10] = "October">
<cfset aArray[12] = "December"> Then the second solution wouldn't work since the position of the element is unknown. Only the first one would work with a little conditioning:

<cfloop from="1" to="#arrayLen(aArray)#" index="i">
   <cfif arrayIndexExists(aArray, i)>
      <cfoutput>#i#: #aArray[i]#<br></cfoutput>
   </cfif>
</cfloop>

In other engines you may have to use <cfif ArrayIsDefined(aArray[i])> if possible. But why not use a very nice way of looping over arrays by using the collection loop (This, BTW, only works on Railo):

<cfset aArray = ["January","February","March","April","May","June","July",
"August","September","October","November","December"]>

<cfloop collection="#aArray#" item="i">
   <cfoutput>#i#: #aArray[i]#<br></cfoutput>
</cfloop>
<br>
<cfset aArray = []>
<cfset aArray[2] = "February">
<cfset aArray[4] = "April">
<cfset aArray[6] = "June">
<cfset aArray[8] = "August">
<cfset aArray[10] = "October">
<cfset aArray[12] = "December">

<cfloop collection="#aArray#" item="i">
   <cfoutput>#i#: #aArray[i]#<br></cfoutput>
</cfloop>

The generated output is:

1: January
2: February
3: March
4: April
5: May
6: June
7: July
8: August
9: September
10: October
11: November
12: December

2: February
4: April
6: June
8: August
10: October
12: December

So using the collection notation in really helps you speed up coding and even respects empty indexes.

 

Tags: Comparison · HowTo · Tips

1 response so far ↓

  • 1 Michael // May 9, 2013 at 10:38 AM

    Lovely syntax! Leaps ahead of the ACF engine. Keep up the good work guys. I came here for a nice way to loop arrays and it delivered!

Leave a Comment

Leave this field empty: