ColdFusion and trailing comma - coldfusion

How do I remove a trailing comma from a string in ColdFusion?

To remove a trailing comma (if it exists):
REReplace(list, ",$", "")
To strip one or more trailing commas:
REReplace(list, ",+$", "")

Also easy:
<cfset CleanList = ListChangeDelims(DirtyList, ",", ",")>
Explanation: This takes advantage of the fact that CF list functions ignore empty elements. ListChangeDelims() consequently strips off that last "element".

Check the rightmost char - if it's a comma, set the string to a substring of the original, with length -1.
Trimming the string ensures that spaces after the trailing comma don't interfere with this method.
<cfset myStr = "hello, goodbye,">
<cfset myStr = trim(myStr)>
<cfif right(myStr, 1) is ",">
<cfset myStr = left(myStr, len(myStr)-1)>
</cfif>

This is probably more of a performance hit than Regex'ing a list, but sometimes when I end up filtering/fixing dirty data, I convert it to an array and then convert it back into a list.
<cfset someVariable = arrayToList(listToArray(someVariable, ","), ",")>
It's cheating, but it works ;-)

To add onto Patrick's answer. To replace one or more commas at the end use the following:
reReplace(myString, ",+$", "", "all")
Example Below
<cfset myString = "This is the string, with training commas,,,">
<cfset onlyTheLastTrailingComma = reReplace(myString, ",$", "", "all")>
<cfset allTrailingCommas = reReplace(myString, ",+$", "", "all")>
<cfoutput>#onlyTheLastTrailingComma#<br />#allTrailingCommas#</cfoutput>

Remove "," from Both Sides, Just the Right Side, or Just the Left Side
<cfset theFunnyList = ",!#2ed32,a,b,c,d,%442,d,a">
Replace Funny Characters and Separate with Comma
<cfset theList = rereplace(theFunnyList, "[^A-Za-z0-9]+", ",", "all")>
<cfset theList = trim(theList)>
<cfif left(theList, 1) is "," and right(theList, 1) is ",">
<cfset theList = right(theList, len(theList)-1)>
<cfset theList = left(theList, len(theList)-1)>
<cfelseif right(theList, 1) is ",">
<cfset theList = left(theList, len(theList)-1)>
<cfelseif left(theList, 1) is ",">
<cfset theList = right(theList, len(theList)-1)>
</cfif>
Sort List (Numeric to A-Z) ASCending
<cfoutput> #ListSort("#theList#", "text", "ASC", ",;")# </cfoutput>

Related

ColdFusion locale specific currency inputs in forms using commas (ie french Canadian 2 222,22$)

Is there an easier/shorter way to convert the final comma of a currency input to a decimal.
Inputs look like 2 000,99 OR 2,000,99
MySQL wants them to look like 2000.99
<cfform action="commatest.cfm?gotime" onsubmit="commatest.cfm" method="post" name="waiv">
<cfinput type="text" name="commer">
<input type="submit" style="width:180px;" value="convertme" class="hide button">
</cfform>
<cfif isdefined("gotime")>
<!--- START SCRIPT --->
<cfset formentry = FORM.commer>
<cfset howlong = #len(formentry)#>
<cfif howlong GT 3>
<cfset leftlen = howlong - 3>
<cfset rside = #right(formentry, 3)#>
<cfset rside = ReReplace(rside,"[,]",".", "ALL")>
<cfset lside = #left(FORM.commer, leftlen)#>
<cfset lside = ReReplaceNoCase(lside,"[-$A-Z,]","", "ALL")>
<cfset lside = reReplace(lside, "[[:space:]]", "", "ALL") />
<cfset newb = #lside# & #rside#>
<!--- OUTPUT TO DATABASE (or webpage in this case) --->
<cfoutput>
<h1>#newb# (number? #IsNumeric(newb)#)</h1>
</cfoutput>
<cfelse>
<cfoutput>
<h1>#formentry# (number? #IsNumeric(formentry)#)</h1>
</cfoutput>
</cfif>
</cfif>
As usual there are several different ways to do this. I would probably do something like this:
<cfscript>
source1 = '2 000,99';
source2 = '2,000,99';
// remove ALL commas and spaces
example1 = REReplace(source1,"[\s,]","","all");
example2 = REReplace(source2,"[\s,]","","all");
// insert a decimal before the last two digits
example1 = Insert(".",example1,(Len(example1)-2));
example2 = Insert(".",example2,(Len(example2)-2));
writeOutput(source1 & " = " & example1);
writeOutput("<br>");
writeOutput(source2 & " = " & example2);
</cfscript>
That code gives the following output:
2 000,99 = 2000.99
2,000,99 = 2000.99
Of course this assumes that the last two digits are always going to be after the decimal point.
Here is a gist of the code above.

Create a list in a loop

I am trying to create a comma separated list inside a loop, but I think I am missing something. When I dump item_id_list, I just get items separated by a space - not a comma. Can anyone point what am I missing?
<cfloop array="data" index="doc">
<cfif structKeyExists(doc, "id") >
<cfset the_item_id = doc.id />
</cfif>
<cfset item_id_list = ''/>
<cfset item_id_list = listappend(item_id_list,'#the_item_id#',',')/>
</cfloop>
Create the list outside of the loop:
<cfset item_id_list = "" />
<cfloop array="#data#" index="doc">
<cfif structKeyExists(doc, "id") >
<cfset item_id_list = listappend(item_id_list, doc.id, ",") />
</cfif>
</cfloop>
Will this work?
<cfset item_id_list = ArrayToList(data.id)>
EDIT: Oops. Can't reference a struct in an array like that. Instead try:
<cfscript>
item_id_list = "" ;
for (row in data) {
if (structkeyexists(row,"id") ) {
item_id_list = listappend(item_id_list,row.id) ;
}
}
</cfscript>
For loops like this, cfscript syntax is easier to see.

CFSpreadsheet Formatting Assistance

I have a spreadsheet query bringing back results. Negative numbers are formatted as ([$$123.12]) and positive numbers are formatted as ("$$123.12").
I need to format the negative number as -123.12 and the positive number as 123.12 before being inserted into a db. What type of regex would I need to use to do that? Or, could I use ColdFusion's Replace() function..and, if so, how?
We created xList as holder for the variable to simulate a looping query.
Assuming negative numbers will always contain "[" and positive numbers don't have the brackets we will loop on the list and check for "[" to format the negative numbers and then format the positive numbers for values not having brackets.
<cfset xlist = '([$$123.12]),("$$123.12")'>
<cfloop list="#xlist#" index="x">
<cfif FindNoCase("[", x )>
<cfset xVal = "-" & rereplaceNoCase(x,"[^0-9.]","","all" )>
<cfelse>
<cfset xVal = rereplaceNoCase(x,"[^0-9.]","","all" )>
</cfif>
<cfdump var="#xVal#"><br>
</cfloop>
Here's a slightly modified version of when I did something similar. Basically, I'm treating the bracket as a negative sign, and stripping out other irrelevant characters, like $. I wasn't clear on whether or not the parenthesis were part of your answer, in which case those would need to be stripped out, too.
<cffunction name="launderMoney">
<cfargument name="value">
<cfset var multiplier = 1>
<cfset arguments.value = Replace(trim(arguments.value), '"', "", "all")>
<cfif Find("[", arguments.value)>
<cfset multiplier = -1>
<cfset arguments.value = Replace(Replace(arguments.value, "[", "", "all"), "]", "", "all")>
</cfif>
<cfset var temp = Trim(Replace(Replace(trim(arguments.value), "$", "", "all"), ",", "", "all"))>
<cfif isNumeric(temp)>
<cfset temp *= multiplier>
</cfif>
<cfreturn temp>
</cffunction>
<p>#LaunderMoney('"$$123.12"')#</p>
<p>#LaunderMoney('[$$123.12]')#</p>

String manipulation Code Changes

The Following Code creates the Codes properly but only issues in the following
<cfset str = "Previoushistory-Diagnosis= 085.2 : Cutaneous leshmaniasis, Asian desert**Controlled-Diagnosis= 085.2 : Asian desert cutaneous leishmaniasis**Controlled-Diagnosis= 153.2 : Cancer of colon, descending colon**Active-Diagnosis= 209.15 : MAL CARCINOID DESC COLON**151.9 : Stomach cancer= UNCONTROLLED">
<cfset string1 = ''>
<cfset generateLst = ''>
<cfset generateLst = ''>
<cfset generateTextlst = ''>
<cfset generateStr = ''>
<cfloop list="#str#" index="elem" delimiters="**">
<cfset string1 = listAppend(string1, elem,'~')>
<cfset delimis = ":">
<cfloop list="#string1#" index="k" delimiters="~">
<cfset getString = GetToken(k,1,'#delimis#')>
<cfset generateStr = ListRemoveDuplicates(ListAppend(generateStr,getString))>
<cfset getID = GetToken(k,2,'#delimis#')>
<cfset generateLst = ListRemoveDuplicates(ListAppend(generateLst,getID))>
<cfset getText = GetToken(k,3,'#delimis#')>
<cfset generateTextlst = ListRemoveDuplicates(ListAppend(generateTextlst,getText))>
</cfloop>
</cfloop>
<cfdump var="#str#"><br /><br>
<cfdump var="#generateStr#"><br /><br />
<cfdump var="#generateLst#"><br /><br />
<cfdump var="#generateTextlst#">
generated Outputs
For generateStr
Previoushistory-Diagnosis= 085.2 ,Controlled-Diagnosis= 085.2 ,Controlled-Diagnosis= 153.2 ,Active-Diagnosis= 209.15 ,151.9
For generateLst
Cutaneous leshmaniasis, Asian desert, Asian desert cutaneous leishmaniasis, Cancer of colon, descending colon, MAL CARCINOID DESC COLON, Stomach cancer= UNCONTROLLED
For generateTextlst
[empty string]
Now the Problem lies in
<cfdump var="#generateStr#"><br /><br />
<cfdump var="#generateLst#"><br /><br />
Now the value for generateStr is coming as:
Previoushistory-Diagnosis= 085.2 ,Controlled-Diagnosis= 085.2
,Controlled-Diagnosis= 153.2 ,Active-Diagnosis= 209.15 ,151.9
can i change it like this
085.2 ,085.2 ,153.2 ,209.15 ,151.9
and use the removed values to append to the second list to which they are relevant like this
Cutaneous leshmaniasis, Asian desert*=Previoushistory-Diagnosis*, Asian
desert cutaneous leishmaniasis*=Controlled-Diagnosis*, Cancer of colon,
descending colon*=Controlled-Diagnosis*, MAL CARCINOID DESC
COLON*=Active-Diagnosis*, Stomach cancer= UNCONTROLLED
i am just confused how do i play with couple of list elements to actually make it happen like the above
Any Guidance
This should be enough to get you started. I modified your cfloop like this:
<cfloop list="#string1#" index="k" delimiters="~">
<cfset getString = GetToken(k,1,'#delimis#')>
<cfset getText = Trim(GetToken(getString,1,'='))> <!--- this returns the text for example Previoushistory-Diagnosis --->
<cfset getValue = Trim(GetToken(getString,2,'='))> <!--- this returns the value for example 085.2 --->
<cfset generateStr = ListRemoveDuplicates(ListAppend(generateStr,getValue))>
<cfset getID = GetToken(k,2,'#delimis#')>
<cfset newText = getID & "=" & getText> <!--- this concatenates the two strings together with = inbetween --->
<cfset generateLst = ListRemoveDuplicates(ListAppend(generateLst,newText))>
<cfset getText = GetToken(k,3,'#delimis#')>
<cfset generateTextlst = ListRemoveDuplicates(ListAppend(generateTextlst,getText))>
</cfloop>
Which outputs generateStr as:
085.2,153.2,209.15,
And generateLst as:
Cutaneous leshmaniasis, Asian desert=Previoushistory-Diagnosis, Cutaneous leshmaniasis, Asian desert cutaneous leishmaniasis=Controlled-Diagnosis, Cancer of colon, descending colon=Controlled-Diagnosis, MAL CARCINOID DESC COLON=Active-Diagnosis, Cutaneous leshmaniasis, Stomach cancer= UNCONTROLLED=151.9
Notice that there is an empty value at the end of the generateStr list. This is because the last value in your str list does not fit the format of the others. The value 151.9 is at the beginning instead of after the = character.
This in turn throws off the generateLst list as well. It makes the last value become Stomach cancer= UNCONTROLLED=151.9, which I assume you do not want.
So you will need to play around with this a bit more to finalize what you need. Obviously these are the kinds of problems that you run into when attempting to parse strings of data that are not consistent.
Something like this might work:
NewList = ListFirst(generateLst); //Cutaneous leshmaniasis
for (i = 2; i lte ListLen(generateLst); i++) {
NewList = ListAppend(ListGetAt(generateLst, i) & "=");
//Cutaneous leshmaniasis, Asian desert=
TempText = ListGetAt(generateStr, i -1); //Previoushistory-Diagnosis= 085.2
TempText2 = ListLast(TempText, "="); // 085.2
NewList &= TempText2; //Cutaneous leshmaniasis, Asian desert=085.2
}
NewList = Replace(NewList, ",", ", ", "all);

ColdFusion 9: Strip HTML tags out of specific parts of a string

I've been cracking my head over this for quite some time.
I currently build a custom BB-Code function as part of a project at work. But I don't get it to work at one point: a [code] block.
Using ColdFusion regex, I want to replace the < and > characters with < and >, but only on HTML betweeen the [code] blocks.
So, how can I restrict a regex expression to the part of the string which is between the [code] blocks.
Thanks in advance for any help.
For those who stumble upon this question and could use an answer as well, I'll provide an example for parsing HTML in [code] blocks. Looks somewhat messy though:
<cfset contents = form.yourString />
<cfset substring1= "[code]" />
<cfset occurrences1 = ( Len(contents) - Len(Replace(contents,substring1,"","ALL"))) / Len(substring1) />
<cfset substring2= "[/code]" />
<cfset occurrences2 = ( Len(contents) - Len(Replace(contents,substring2,"","ALL"))) / Len(substring2) />
<cfif occurrences1 EQ occurrences2 AND occurrences1 GT 0 AND occurrences2 GT 0>
<cfset loopinstance = occurrences1 />
<cfelse>
<cfif occurrences1 LT occurrences2>
<cfset loopinstance = occurrences1 />
<cfelse>
<cfset loopinstance = occurrences2 />
</cfif>
</cfif>
<cfloop index="code_loop" from="1" to="#loopinstance#">
<cfscript>
// prepare variables //
code_string = contents;
startpos = FindNoCase("[code]", code_string);
startpos = Evaluate(startpos + 6); // adjust the correct position of string in question
endpos = FindNoCase("[/code]", code_string);
code_string = Mid(code_string, startpos, Evaluate(endpos - startpos)); // extract the string between code brackets
//** Replace-Codes are extensible depending on the used programming languages **//
code_string = ReplaceNoCase(code_string, "<","<", "ALL");
code_string = ReplaceNoCase(code_string, ">",">", "ALL");
//** process conversion of [code] block **//
startpos = FindNoCase("[code]", contents); // reevaluating the start and end positions for main string
startpos = Evaluate(startpos + 6); // adjust the correct position of form string
endpos = FindNoCase("[/code]", contents);
contents = RemoveChars(contents, startpos, Evaluate(endpos - startpos)); // remove the extracted string
contents = Insert(code_string, contents, Evaluate(startpos - 1)); // insert the processed code block to the original position
contents = ReplaceNoCase(contents, "[code]", "[coded]", "ONE"); // "flagging" the processed [code] block as finished by adding a "d"
contents = ReplaceNoCase(contents, "[/code]", "[/coded]", "ONE"); // "flagging" the processed [code] block as finished by adding a "d"
</cfscript>
</cfloop>
<!--- This is the regex to turn a written [code] block into an escaped HTML block --->
<cfscript>
contents = REReplaceNoCase(contents, "\[coded\](.*?)\[/coded\]", "<div id =""code_test"">Escaped Code: <br />\1</div>", "ALL");
</cfscript>
I hope this will help some people who have a hard time following #David Faber's help.
I think in ColdFusion you'll have to iterate over the string, searching for occurrences of "[code]". When you find such an occurrence, read in the string until you hit "[/code]". Take that string and do a replaceList to replace the characters. Use the removeChars and insert functions to replace the old string with the new. One problem with using regular expressions in this context is that the CF function REReplace can't replace a pattern with another pattern, only with a string.