Any Better Way to Loop Through a Collection (Struct) in Cfml?
Please Have a Look at the Code Block Below: #Key#: #Anotherperson[Key]#, Now Can You Please Tell Me How Could I Achieve the Same Result Without Setting an...
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!
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( ', ' ) );
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!
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.