I am trying to itterate over a list that is delimi...
# cfml-general
c
I am trying to itterate over a list that is delimited with '\n' using cfloop, but it keeps delimiting at every 'n' is the backslash a special character for cfloop? Any ideas how to make this work?
Copy code
<!--- sample errors --->
<cfsavecontent variable="session.orderEntryData.shipment.errors">
                        <cfoutput>Error 1: Invalid shipping address.\nError 2: Payment method declined.\nError 3: Item out of stock.\nError 4: Invalid coupon code.\nError 5: Exceeded maximum order quantity.</cfoutput>
                    </cfsavecontent>


                    <div class="col-lg-12">
                        <!--- error handling --->
                        <div class="container p-3 mt-4 border rounded border-danger">
                            <div class="row ">
                                <div class="col-12 p-2 pt-1" >
                                    <div class="row">
                                        <div class="col-12">
                                            <!--- Header Text --->
                                            <div class="row">
                                                <div class="col-11 align-middle mb-3 justify-content-center d-flex">
                                                    <span class="text-left route-card-header text-danger" >Your submission generated the folowing errors</span>
                                                </div>
                                            </div>
                                            <div class="row">
                                                <div class="col-12">
                                                    <cfloop list="#session.orderEntryData.shipment.errors#" delimiters="\n" index="error">
                                                        <div class="alert alert-danger" role="alert">
                                                            <cfoutput>#error#</cfoutput>
                                                        </div>
                                                    </cfloop>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
e
did you try using the character code for \ ? e.g. delimiters="#chr('\')#n"
c
no, will give it a try now thanks
that did the same thing
tried -
delimiters="#chr(92)#n"
m
\n is not a special character in ColdFusion you will need to create a variable that contains your CR there are multiple ways to do this including chr(10), you just need to bemindful of what line endings on your OS are... in one of my systems i have special constants to hold these values: "CRLF" : CHR(13) & CHR(10), "CR" : CHR(10),
šŸ‘ 1
c
<cfset delim=chr(92)&"n">
<cfloop list="#session.orderEntryData.shipment.errors#" delimiters="#delim#" index="error">
<div class="alert alert-danger" role="alert">
<cfoutput>#error#</cfoutput>
</div>
</cfloop>
same result
c
You could also try replacing all of the "\n" with a safe delimiter character like a pipe
|
character, then loop using the new delimiter.
šŸ‘ 1
c
will try that
That worked thanks!
šŸ‘ 1
Copy code
<cfloop list="#replaceNoCase(session.orderEntryData.shipment.errors,'\n','|','all')#" delimiters="|" index="error">
                                                        <div class="alert alert-danger" role="alert">
                                                            <cfoutput>#error#</cfoutput>
                                                        </div>
                                                    </cfloop>
e
awesome!
c
i used three pipes as the delimeter just incase there is a single one somewhere, i dont know what the output of the api is going to be.
m
I believe <cfloop list excepts multiple delimiters if you are doing a replacement i would replace on a character you might never have in your data like chr(29) ASCII Code 29 - Group Separator
c
@Michael Schmidt thanks i made the change!
b
Michael is correct-- each char is individually used as a delim, it's not a single delimiter string. Doing a replace is the best approach, if possible. Otherwise, you'd need to do a manual find in a loop.
d
Just to say it, if possible I'd convert the list to an array and iterate over that instead. You'll still need to figure out hat delimiters to use converting to an array, but the code will be nicer, and I'd expect performance to improve too, since you're only parsing the list once.
šŸ‘ 1
b
Presumably, cfloop only parses the string once already
I would expect it to be the same amount of worth whether you • ask cfloop to iterate over a list • ask listtoArray() to iterate over a list
šŸŽÆ 1
You're just kicking a can down the road so to speak
d
Unless cf is smart enough to parse the list into an array itself under the hood, it's going to be dealing with that loop as a bunch of string finding -- where's the next delimiter etc. Maybe it is, and I haven't tested performance of those two strategies for a number of years, but converting to an array ONCE used to be a lot faster.
b
That's exactly what it does. Well, I can't see Adobe's source like I can BoxLang and Lucee, but it's a 99% certainty Adobe follows suit. When you cfloop over a list, the array is created internally and then dealt with from there.
Here's where Lucee generates the bytecode for their cfloop tag that delegates to their listUtil-- the same util that powers
listToArray()
. https://github.com/lucee/Lucee/blob/6.2/core/src/main/java/lucee/transformer/bytecode/statement/tag/TagLoop.java#L748
Here's where BoxLang's loop component delegates to our ListUtil-- the same one that powers our
listToArray()
https://github.com/ortus-boxlang/BoxLang/blob/development/src/main/java/ortus/boxlang/runtime/components/system/Loop.java#L130
All internal looping in this case is done directly over the converted array so the string is not touched once it's converted to an array
d
Cool, then you're right, no reason to explicitly convert to an array, unless you like that form of iteration better, which I do šŸ™‚
b
Agreed. If I'm doing anything else at all with the data, I'd much rather have an array on hand!
I would typically turn it into an array first just to get it into a more manageable format, and then deal with it as an array for then on out for convenience
šŸ‘ 1
d
Yeah we're on the same page then.
šŸ‘ 1
m
The list structure in ColdFusion is both a gift and a curse. It is powerful, but sometimes to powerful, if you know you know.