2

I have an array called device, which looks like this (simplified):

label : "Device 1",
exhibits : [{
    item : 1,
    desc : "This is a sample"
},{
    item : 2,
    desc : "This is another sample"
},{
    item : 3,
    desc : "This is a third"
}]

I'm trying to print exhibits neatly for a PDF, so I'm thinking comma-deliniated like this:

1, 2, 3

This is my code:

<cfloop array="#device.exhibits#" index="exhibit">
    #exhibit.item#
</cfloop>

But I get this:

123

Yes, I could manually figure out if there should be commas or not, but is there a better way to do this?

3
  • You could so some sort of listappend() but that would not get the spaces. Commented Nov 16, 2018 at 17:53
  • 1
    My compiler sense is tingling: itemNumber is undefined in exhibit. You meant #exhibit.item#, right? :P Commented Nov 16, 2018 at 23:59
  • @Alex Yes, thank you, I fixed it to match. Commented Nov 18, 2018 at 13:05

2 Answers 2

3

Since you're using CF11+, you can use the ArrayMap function with an ArrayList to turn the array into a list.

exhibits.map( function(i) { return i.item ; } ).toList() ;

With your example array, it gives you "1,2,3".

In another of my answers, I stepped through handling empty elements. Since this is an array of structs, I don't know if this would be a problem. How are you getting this data for your exhibits array?

EDIT:

exhibits.map( function(i) { return i.item ; } )
    .filter( function(j) { return len(j) ; } )
    .toList() ;

will return the list with empty elements removed.

EDIT 2:

Per the question by @TravisHeeter, if you prefer lambda expressions or arrow functions, you can use them in Lucee 5.

exhibits.map( (i) => i.item ).filter( (j) => len(j) ).toList()

https://trycf.com/gist/907a68127ddb704611b191d494aa94ce/lucee5?theme=monokai

Sign up to request clarification or add additional context in comments.

5 Comments

I take it CF doesn't have arrow functions yet?
@TravisHeeter I don't think Adobe CF does, but Lucee 5 dialect does. See answer update.
Unfortunately, I could not get .map nor arrayMap to work, I had to use @Alex's solution.
Are you using CF2016? ArrayMap was added back in CF11, so there's no reason it shouldn't work on any modern version of CF. What does your array look like? It may be a referencing problem.
trycf.com/gist/549906a224a65edeba15b8a60674ab0e/… << I nested the array like your example, with device being the outer array, and by changing the reference to device.exhibits, it still works. Does your device array have a more complex structure?
2

The usual approach is to extract the data first:

<!--- extract the itemNumber of every exhibit --->
<cfset itemNumberList = []>
<cfloop array="#device.exhibits#" index="exhibit">
    <cfset itemNumberList.add(exhibit.itemNumber)>
</cfloop>

And then we transform the extracted data to a comma-separated list (string):

<cfset itemNumberList = arrayToList(itemNumberList, ", ")>

<!--- 1, 2, 3 --->
<cfoutput>#itemNumberList#</cfoutput>

Array-mapping (see Shawn's answer) is a more fancy (readable?) way.

1 Comment

Just realized that .add() falls back into Java. .append() is the CF member function. Personally, I think this integration with parts of Java is one of the very nice things about ColdFusion. I think that Java .add() when building an array is fastest.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.