Change the List delimiter to something new - coldfusion

I am trying to change the delimiters of a list. So far I have been successful, but am losing ground on one of the actions.
The issue is the with the last element, which is v. The code never appends ="" to the last element. It should not add a comma to it.
Code:
<cfset foo="t,u,n,f,o,a,c,r,v">
<cfset msg = ListChangeDelims(foo,'="",')>
<cfoutput>#msg#</cfoutput>
Result:
t="",u="",n="",f="",o="",a="",c="",r="",v
I hope my question makes sense.

That is the definition of delimiter. Anyway, it is relatively easy to fix, just add the last one yourself.
<cfset foo="t,u,n,f,o,a,c,r,v">
<cfset msg = ListChangeDelims(foo,'="",')>
<cfset msg &= '=""'>
<cfoutput>#msg#</cfoutput>
http://trycf.com/gist/4ac3702b74bd79b5d1f8/

There is always the old fashioned way
msg = replace(foo,",","=", "all");

Related

Why is ListAppend non destructive, while ArrayAppend and StructInsert are both destructive?

I just spent almost an hour trying to figure out an issue with having a list that would always return an empty string. I was using ListAppend just like one uses ArrayAppend or StructInsert, but apparently ListAppend works differently. What, if any, is the reasoning behind having ListAppend work differently from everything else?
<cfset ListAppend(list, item)>
list = ''
<cfset ArrayAppend(array, item)>
array[1] = item
<cfset StructInsert(struct, 'key', item)>
struct.key = item
Possibly because a list is just a big String. Unlike arrays and structures, Strings are immutable, meaning they cannot be changed. To "append" a new value, you need to create an entirely new String. Arrays and structures are mutable. So you can modify them "in place".
Lists in ColdFusion are just Strings and strings in ColdFusion (and Java) are immutable. They cannot be changed. So ListAppend() must return the a new string with the value instead of modifying the existing string.
<cfset newList = listAppend(oldList, "New Value") />

ColdFusion-9 "includeEmptyValues"

This is my code:
returnStruct.myList = myList;
returnStruct.first = trim(ListGetAt(myList,3));
returnStruct.last = trim(ListGetAt(myList,13));
returnStruct.address = trim(ListGetAt(myList,15));
returnStruct.city = trim(ListGetAt(myList,2));
returnStruct.state = trim(ListGetAt(myList,9));
Everything is working fine until myList hits empty values and then everything crashes.
I found a command "includeEmptyValues" that I can set to 'yes' but I am not familiar with it and the documentation of ColdFusion 9 isn't the best I've come across.
http://cfquickdocs.com/cf9/#listgetat
Previous versions of ColdFusion (and CF9 by default) counted consecutive delimiters as a single delimiter. So a list that looked like this:
<cfset myList="a,b,,c,,d" />
was considered to have four elements.
Recently added is the "includeEmptyValues" attribute.
listGetAt(list, position [, delimiters, includeEmptyValues ])
So while
<cfset myVar=listGetAt(myList,6) />
will throw an error
<cfset myVar=listGetAt(myList,6,",","true") />
will successfully set myVar to d.
might want to use listToArray(), and ArrayIsDefined(). Play with includeEmptyFields attr and see which behavior you prefer. True = Convert empty elements in a list to empty array entries

The value cannot be converted to a number

Got a critical error like: The value cannot be converted to a number. what can be the problem? Since i tried to write this values like:
1. <cfset ortalama=trim(val(db_maliyet_temp))+ds_toplam_maliyet>
2. <cfset ortalama=val(db_maliyet_temp)+ds_toplam_maliyet>
3. <cfset ortalama=db_maliyet_temp+ds_toplam_maliyet>
the first and second are just doesnt count the db_maliyet_temp,
and the 3 give out the error: The value cannot be converted to a number.
value for db_maliyet_temp: 2.806,71
for ds_toplam_maliyet: 394,22
These are not valid numbers. If you would like the total of the numbers, you can try this.
<cfset aryMaliyetNumbers = ListToArray(db_maliyet_temp, ",")>
<cfset aryToplamNumbers = ListToArray(ds_toplam_maliyet, ",")>
<cfset total = ArraySum(aryMaliyetNumbers) + ArraySum(aryToplamNumbers)>
There are several ways to skin this cat. This should at least get you going. Works perfectly on my CF 7 box!
EDIT
After the ridiculous amount of comments to clarify the question, I believe this is the solution.
<cfset db_maliyet_temp = Replace(Replace("2.806,71", ".", ""), ",", ".")>
<cfset ds_toplam_maliyet = Replace(Replace("394,22", ".", ""), ",", ".")>
<cfset total = db_maliyet_temp + ds_toplam_maliyet>
If you want the number without decimals, you can do this:
<cfset db_maliyet_temp = Replace(Replace("2.806,71", ".", ""), ",", ".")>
<cfset ds_toplam_maliyet = Replace(Replace("394,22", ".", ""), ",", ".")>
<cfset total = val(db_maliyet_temp + ds_toplam_maliyet)>
IMPORTANT
You have a much larger problem than a CF error. You need to fix the underlying issue that's causing your number to be formatted incorrectly.
This should do the trick:
<cfscript>
function convertToNumber(num){
return reReplace(reReplace(num,'.','','ALL'),',','.','ALL');
}
</cfscript>
<cfset ortalama=convertToNumber(db_maliyet_temp)+convertToNumber(ds_toplam_maliyet)>
Basically it just removes the '.' since that is formatting not needed for math and replaces the ',' with a decimal so that it can be treated as a number. This will only work if ALL the numbers you are going to be dealing with are formatted this way, if there are any formatted like 1,200.90 then you will have to be a little more fancy.
Have you tried the LSParseNumber() function?:
http://cfquickdocs.com/cf9/#lsparsenumber
Or the val() function?:
http://cfquickdocs.com/cf9/#val
Also, it may be easier to clean the data before it get's entered either with client-side validation (if it's coming from a form) or server-side validation.

Use string function to select all text after specific character

How would I use use a string function to select everything in a variable after the last "/"
http://domain.com/g34/abctest.html
So in this case I would like to select "abctest.html"
Running ColdFusion 8.
Any suggestions?
Um, a bit strange to give very similar answer within few days, but ListLast looks as most compact and straightforward approach:
<cfset filename = ListLast("http://domain.com/g34/abctest.html","/") />
And yes, IMO you should start with this page before asking such questions on SO.
Joe I'd use the listToArray function, passing the "/" as the delimiter, get the length of the array and get the value in the last slot. See sample below
<cfset str = "http://domain.com/g34/abctest.html"/>
<cfset arr = ListToArray(str,"/","false")/>
<cfset val = arr[ArrayLen(arr)]/>
<cfoutput>#str# : #val#</cfoutput>
produces
http://domain.com/g34/abctest.html : abctest.html

How do I get the contents of a string minus the extension in ColdFusion?

For example, I want just the "filename" of a file in a field. Say I have myimage.jpg I only want to display "myimage" How do I get just that?
Use the List functions to your advantage.
<cfset FileName = ListDeleteAt(FileFullName, ListLen(FileFullName, "."), ".")>
Be aware that this only works for file names that actually have a file extension (that is defined as the thing after the last dot). To make it safer, the following is better:
<cfset ExtensionIndex = ListLen(FileFullName, ".")>
<cfif ExtensionIndex gt 1>
<cfset FileExt = ListGetAt(ExtensionIndex , ".")>
<cfset FileName = ListDeleteAt(FileFullName, ExtensionIndex, ".")>
<cfelse>
<cfset FileExt = "">
<cfset FileName = FileFullName>
</cfif>
To complicate things a bit further: There may be files that start with a dot. There may be file names that contain many adjacent dots. List functions return wrong results for them, as they ignore empty list elements. There may also be files that have dots, but no extension. These can only be handled if you provide an extension white list: ListFindNoCase(FileExt, "doc,xls,ppt,jpg"). If you want to account for all of this, you probably need to resign to a reguar expression:
<cfset FileExtRe = "(?:\.(?:doc|xls|ppt|jpg))?$">
<cfset FileName = REReplaceNoCase(FileFullName, FileExtRe, "")>
To split file name from path, ColdFusion provides distinct functions that also handle platform differences: GetFileFromPath() and GetDirectoryFromPath()
Tomalak's answer is good, but this can get tricky. Given a file named "mydoc.ver1.doc" (a valid Windows file name) which is the filename and which is the extension? What if there is a filepath?
You can still leverage the list functions to your advantage, however, even in these scenarios.
You can easily parse out the file from the path with
fullFileName=listLast(fieldname,"\/")
If you assume the filename is everything before the dot, then
theFileName=listFirst(fullFileName,".")
will work.
If you want to ensure that you get everything but what's after the last period, then a little trickery is needed, but not much. There is not a listAllButLast() function (although such a thing might exist on CFLIB.org) but there are two ways I can think of to get what you're after.
fileName=reverse(listRest(reverse(fullFileName),"."))
or
fileName=listDeleteAt(fullFileName,listLen(fullFileName,"."),".")
As with Tomalak's suggestion, however, this will break down on a filename that lacks an extension. Wrapping this in a <cfif listLen(fullFileName,".") GT 1> will account for that.
The current accepted solution will not work for a file that does not contain an extension.
You can solve this by using a regular expression to strip the extension only if it exists:
<cfset FileName = rereplace( FullFileName , '\.[^.]+$' , '' ) />
This might still not be perfect - you might have a file that has a . but it isn't considered an extension - you can solve this either by using a list of known extensions to strip, or by limiting how long an extension you will accept (e.g. upto 5):
<cfset FileName = rereplace( FullFileName , '\.(jpg|png|gif|bmp)$' , '' ) />
<cfset FileName = rereplace( FullFileName , '\.[^.]{1,5}$' , '' ) />
So you first need to find the position of the last fullstop (there could be more than one fullstop in the full filename). I don't think Coldfusion has a find function that works backwards, so reverse the string first:
<cfset Position = Find(".", Reverse(FullFileName))>
If that returns zero then you don't have a fullstop in the file name, so handle appropriately. Else ...
<cfset Filename = Left(FullFileName, Len(FullFileName) - Position>
As of ColdFusion 9+ (perhaps earlier, but I can't verify), the Apache Commons library was included. Within that is org.apache.commons.io.FilenameUtils. You can utilize methods within the cut down on the amount of operations needed in CF to get the same (or similar) results.
filepath = "some/dir/archive.tar.gz";
oUtils = createObject("java", "org.apache.commons.io.FilenameUtils");
writeDump(oUtils.getFullPath(filepath)); // "some/dir/"
writeDump(oUtils.getName(filepath)); // "archive.tar.gz"
writeDump(oUtils.getBaseName(filepath)); // "archive.tar"
writeDump(oUtils.getExtension(filepath)); // "gz"
writeDump(oUtils.getPath(filepath)); // "some/dir/"
writeDump(oUtils.getPathNoEndSeparator(filepath)); // "some/dir"