Looping over lists in cf9
Asked Answered
T

3

12

Page 116 of the developer's guide says "Unlike the cfloop tag, CFScript for-in loops do not provide built-in support for looping over queries and lists."

Q: How do I loop over a list using the new script syntax in ColdFusion 9?

<cfloop list="#qry.Columnlist#" index="FieldName">
   <cfset form[FieldName] = qry[FieldName][1]>
</cfloop>
Terret answered 7/1, 2010 at 14:3 Comment(1)
Adam Cameron has put together a fantastic resource at github.com/daccfml/cfscript/blob/master/cfscript.mdTerret
B
18

You can also try the listToArray and then use the for-in construct for Arrays in CF9 as:

<cfscript>
aCol = listToArray (qry.ColumnList);

for( fieldName in aCol ){
    form[fieldName]  = qry[fieldName][1];
}

</cfscript>
Brit answered 29/3, 2011 at 14:38 Comment(3)
Note that this works but only with Update 1 installed. The original CF9 will give an error since for-in was only allowed on struct's.Jehoshaphat
Is the intermediate variable aCol necessary in this example? Wouldn't for(fieldName in ListToArray(qry.ColumnList)) be cleaner (less scope pollution)?Bo
Will it create additional array variable, that implicates additional memory allocation? Does that mean that cfloop tag is more efficient than doing such stuff in cfscript? I am asking this because I want to persuade team to use cfscript, but they giving this point as a disadvantage.Lamson
P
12
<cfscript>
  var i = 0;
  var l = ListLen(qry.Columnlist);
  var FieldName = "";
  for (i = 1; i lte l; i = i + 1)  // you also can use i++ instead
  {
    FieldName = ListGetAt(qry.Columnlist, i);
    form[FieldName] = qry[FieldName][1];
  }
</cfscript>

EDIT Nicer (maybe a even little faster, for really heavy loops) version of the above:

<cfscript>
  var i = 0;
  var Fields = ListToArray(qry.Columnlist);
  var FieldName = "";
  var l = arrayLen(Fields);
  for (i = 1; i lte l; i = i + 1)  // you also can use i++ instead
  {
    FieldName = Fields[i];
    form[FieldName] = qry[FieldName][1];
  }
</cfscript>
Philtre answered 7/1, 2010 at 14:14 Comment(2)
Slightly shorter form: for (i = 1; i <= qry.RecordCount; i++) {}Persistence
@Sergii: That's the whole point - it's not about the RecordCount, but about the length of the ColumnList. ;-)Philtre
L
5

I would turn the list into an array first. ListGetAt() is not efficient to be called n times in a loop. ArrayLen() however should be quite fast.

<cfscript>
arr = ListToArray(qry.Columnlist);

for (i = 1; i <= ArrayLen(arr); i++)
{
    fieldName = arr[i];
    form[FieldName] = qry[FieldName][1];
}
</cfscript>
Lala answered 7/1, 2010 at 19:37 Comment(7)
wouldn't it also be faster to call ArrayLen just once and store it in a variable?Sideband
yes it would. Just wanna keep the code segment small and neatLala
that makes sense ... and it's more readable using fieldName than arr[i].Sideband
I'd probably use a for(element in array) loop here, Henry. You only need the index value here to get the element, so you might as well not bother with it.Glarum
@AdamCameron... it was answered back in 2010 and I doubt for-in loop for array was mature or even existed. :)Lala
ColdFusion 9? Sure they did. And I wouldn't've suggested it if it wasn't an appropriate suggestion.Glarum
@AdamCameron see DaveBurns comment with 3 up votes on the other answer.Lala

© 2022 - 2024 — McMap. All rights reserved.