Any Better Way to Loop Through a Collection (Struct) in Cfml?

Please have a look at the code block below:

<cfset index = 0 />
<cfloop collection="#anotherPerson#" item="key" >
    <cfset index = index+1 />
    <cfoutput> 
         #key# : #anotherPerson[key]# 
         <cfif index lt ArrayLen(structKeyArray(anotherPerson))> , </cfif>
    </cfoutput>
</cfloop>

<!--- Result 

   age : 24 , haar : Blondes haar , sex : female , ort : Hanau

---->

Now can you please tell me how could I achieve the same result without setting an index outside and incrementing it inside the loop? If you notice carefully, I had to write two more cfset tag and one cfif tag with expensive code just to avoid a comma (,) at the end of the collection!

4

3 Answers

Ok, I'm showing you two answers. The first will run on ColdFusion 9. Since other people might find this thread and be using Lucee Server or a newer version of Adobe ColdFusion, I'm including a one-liner that uses higher order functions and runs on ACF 2016. There's a lot of syntactic sugar (like member functions) and functional programming you're missing by being on CF9. These answers use script, because manipulating data is not something for a view (where tags/templating are used).

Set up the data

myStruct = { 'age'=24, 'haar'='Blondes haar', 'sex'='female', 'ort'='Hanau' };

CF9 compat, convert data to array and use delimiter to add commas

myArray = [];
for( key in myStruct ) {
    arrayAppend( myArray, key & ' : ' & myStruct[ key ] );
}
writeOutput( arrayToList( myArray, ', ' ) );

Modern CFML. Use struct reduction closure to convert each key into an aggregated array which is then turned into a list.

writeOutput( myStruct.reduce( function(r,k,v,s){ return r.append( k & ' : ' & s[ k ] );  }, [] ).toList( ', ' ) );
4

Some friends provided two different solutions. Both are efficient and elegant!

Solution 1

<cfset isFirst = true />
<cfloop collection="#anotherPerson#" item="key" >
    <cfif isFirst>
        <cfset isFirst = false />
    <cfelse> 
        ,   
    </cfif> 
    <cfoutput> 
       #key# : #anotherPerson[key]# 
    </cfoutput>
</cfloop>

Solution 2

<cfset resultList = "" />
<cfloop collection="#anotherPerson#" item="key" >
    <cfset resultList = ListAppend(resultList, "#key# : #anotherPerson[key]#" ) />
</cfloop>

Cheers!

1

Just trim the comma when you are done, no skip logic required.

<cfset html = '' />
<cfloop collection="#anotherPerson#" item="key" >
    <cfset html &= "#key# : #anotherPerson[key]# , " />
</cfloop>
<cfset html = left(html,len(html)-3) />

<cfoutput>#html#</cfoutput>

Readable, simple, works.

3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest