6

Hi I have a loop which outputs

<cfloop collection="#SESSION.squad.achievements#" item="key">

The problem is the key(which is a year) is output in the wrong order, it outputs

2009

2010

2011

As far as I can see there in no built in method for changing the order or am I missing something?

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
Ross Mark
  • 63
  • 1
  • 3

2 Answers2

10

Coldfusion structures don't have an order, so you can't guarantee when looping over a struct that the keys will come out in the same order they were inserted (or numerically/alphabetically/etc).

If the order is important, use an array instead.

An alternative would be to get all the keys in an array, then order that array, and loop over it, but inside the loop referencing the structure.

<!--- get an array of the keys in the desired order --->
<cfset achievements = StructSort(SESSION.squad.achievements, "numeric", "desc")>

<!--- loop over that array --->
<cfloop index="year" array="#achievements#">
    <!--- refer back to the struct, keyed on the current year we're looping on --->
    #year# : #SESSION.squad.achievements[year]#
</cfloop>
duncan
  • 31,401
  • 13
  • 78
  • 99
  • 2
    You can also use the StructSort function to avoid the need to create the initial array and sort it. It's then a onestep process to get the keys in the right order before running through the loop. http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_s_30.html – Dan Short May 03 '11 at 12:10
  • Nice one, a function I'd forgotten about. I'll update my example code to use that instead. – duncan May 03 '11 at 12:49
  • good answers, would be nice to have this build in as a optional method. But is no biggie as a couple of lines sort it. – Ross Mark May 04 '11 at 07:58
2

Instead of this:

<cfset SESSION.squad.achievements = StructNew() />

Use this:

<cfset SESSION.squad.achievements = createObject("java", "java.util.LinkedHashMap").init() />

This will maintain the order.

Source: http://www.aftergeek.com/2010/03/preserving-structure-sort-order-in.html

Deepak Yadav
  • 1,724
  • 3
  • 23
  • 38
  • Yes. Just keep in mind that unlike CF structures, LinkedHashMap's are case sensitive. So functions like structKeyExists may return a different result if you are not careful to use the same case across the board. – Leigh Oct 30 '15 at 17:46
  • @Leigh When I use createObject("java", "java.util.LinkedHashMap"), it orders things alphabetically. This is driving me nuts. I want it to retain definition order. What gives? – Charles Robertson Sep 12 '16 at 13:33
  • @Leigh Just an update on this. If I start the key with a capital letter, it works. But, if all the letters of the key are lower case, it orders alphabetically. Is this a bug? – Charles Robertson Sep 12 '16 at 13:36
  • @Leigh Sorry. The previous comment is wrong. Even, if I capitalise the first letter of the key, it returns the struct keys alphabetically... – Charles Robertson Sep 12 '16 at 13:40
  • @Leigh I really am an idiot. This alphabetical issue ONLY happens when I CFDUMP. If I use , it works correctly. Sorry people... – Charles Robertson Sep 12 '16 at 13:55
  • 1
    @CharlesRobertson - Lol, no worries. cfdump's bias towards user friendly output gets me sometimes too. It is a great tool, but it is not always 100% "truthful" ;-) – Leigh Sep 12 '16 at 18:56
  • 1
    (Edit) @CharlesRobertson - Lol, cfdump's bias towards user friendly output gets me sometimes too. It is a great tool, but it is not always 100% "truthful" ;-) BTW, LinkedHashMap has some nuances you may not be expecting (example it is case sensitive). To avoid common gotchas, you may want to stick with the [accepted answer](http://stackoverflow.com/a/5868008/104223). – Leigh Sep 12 '16 at 20:26