I am sending a comma delimited list from a formset and each of the possible selected items except the first can only be added if the first is not selected.
QUANTY=10-1,1-0,2-0,3-0,4-0,5-0,7-0,6-0,8-0,9-0,15-0,13-0
Each element in the list is a number, a hyphen and another number. The first number is the product number and the second is quantity.
If the first element in the list is 10-1 you cannot add any other items so they would have to be number -0 as in 3-0.
This statement works if any of the other elements contain -1
<cfif ListFirst(QUANTY) IS "10-1" AND ListRest(QUANTY) contains "-1">
<tr>
<td align="center">
<font color="#FF0000"><strong>
You cannot add any features to the Basic Plan<p>
Please click "Back" and reset your order.
</strong></font>
</td>
</tr>
<cfabort>
</cfif>
The problem arises when a quantity larger than 1 is selected as in:
QUANTY=10-1,1-0,2-0,3-0,4-0,5-0,7-0,6-0,8-4,9-0,15-0,13-0
I cannot seem to get the "Between" function to work in the part of my cfif statement:
AND ListRest(QUANTY) contains "-1">
as in:
AND ListRest(QUANTY) BETWEEN "-1" and "-50">
Any suggestions appreciated
ListRest(quanty) contains "1"
will return true on values such as "1-0". That's clearly not what you want.
I suggest treating your string as nested lists. The outer list is comma delimeted and the inner is hyphen delimited. This approach should work
<cfif ListLast(ListFirst, Quanty, ","), "-") gt "0">
loop through the rest of Quanty and use ListLast to check
the values after the hyphen
<cfelse>
code for this condition
</cfif>
I tried the script above and got an error on the ,...
I wrote this and it seems to work ok:
<cfset qty1 = "#ListFirst(QUANTY)#">
<cfset qty2 = ListLast(qty1, "-")>
<cfif (qty2 GT 0) AND
((ListRest(QUANTY) contains "-1") OR
(ListRest(QUANTY) contains "-2") OR
(ListRest(QUANTY) contains "-3") OR
(ListRest(QUANTY) contains "-4") OR
(ListRest(QUANTY) contains "-5") OR
(ListRest(QUANTY) contains "-6") OR
(ListRest(QUANTY) contains "-7") OR
(ListRest(QUANTY) contains "-8") OR
(ListRest(QUANTY) contains "-9"))>
do this
</cfif>
Thanks and if there is a shorter way to write it I would appreciate the input.
Your solution should work, but a Regular Expression might be more elegant.
<cfif ListFirst(QUANTY) is "10-1" and REFind("-[1-9]",ListRest(QUANTY))>
Do something
</cfif>
Should work. Reg Expressions are really helpful. If you haven't used them before, the one above looks for a dash followed by a number from 1 to 9.
I would suggest just using a regex by itself (no need to do list manipulation to check if a pattern exists):
<cfif REFind("^[0-9]+-[1-9].+-[1-9]", QUANTITY)>
<tr>
<td align="center">
<font color="#FF0000"><strong>
You cannot add any features to the Basic Plan<p>
Please click "Back" and reset your order.
</strong></font>
</td>
</tr>
<cfabort>
</cfif>
Tested on the following:
"10-1,1-0,2-0,3-0,4-0,5-0,7-0,6-0,8-0,9-0,15-0,13-0" no match (pass)
"10-0,1-5,2-0,3-0,4-0,5-0,7-0,6-0,8-0,9-0,15-0,13-0" no match
"9-1,1-5,2-0,3-0,4-0,5-0,7-0,6-0,8-0,9-0,15-0,13-0" match (fail)
"10-1,1-5,2-0,3-0,4-0,5-0,7-0,6-0,8-0,9-0,15-0,13-0" match
"11-1,1-5,2-0,3-0,4-0,5-0,7-0,6-0,8-0,9-0,15-0,13-0" match
"10-1,1-0,2-0,3-0,4-0,5-0,7-5,6-0,8-0,9-0,15-0,13-0" match
Related
How can I detect if a string value only consists of one or more commas and nothing else. The correct value should be something like: ABC,BVC,BNM but sometimes I get value like: , or ,,, or ,, and this is not allowed. How can I detect that a string only have one or more commas and then I can create a warning to the user and stop the process.
Thank you
You can use listToArray() and arrayToList() to remove the empty items from the list and can then compare the sanitized version with the original like this:
<cfset originalInput = trim( ",,," )>
<cfset sanitizedInput = arrayToList( listToArray( originalInput, ",", false ), "," )>
<!--- Compare both --->
<cfif originalInput NEQ sanitizedInput>
<!--- Throw error --->
</cfif>
Depends on how much your input may vary, but as you currently describe it:
Something as simple as <cfif MyVar contains ",,"> would work.
If one comma (and nothing else) is a possibility, then
<cfif MyVar contains ",," OR Len(MyVar) lt 2>
Assuming any non-commas are either letters or numbers, you can do use a regular expression:
patternAlphaNumeric = "[0-9a-zA-Z]";
testString = ",,,";
if (reFind(",", testString) > 0 && refind(patternAlphaNumeric, testString) == 0)
code for all commas
else
code for other characters
If you are only concerned about detecting commas (or one or more of any character), just use ListLen().
It's a native ColdFusion function.
It ignores empty list items by default.
Its default delimiter is a comma.
So, if your_string consists only of one or more commas, then ListLen( your_string ) will always return 0.
Heads up, it also returns 0 for an empty string, so if you don't want your code to pop for empty strings, be sure to account for that.
<cfset local.myString = "string-goes-here">
<cfset local.myNewString = ReReplace(trim(local.myString),",","","ALL")>
<cfif not len(local.myNewString)>
<!--- warning to the user and stop the process --->
</cfif>
I have a HUGE string list (I'll limit the example to one line) with the format:
"[First Name] [Last Name] <[email address]>"
I ran a regular expression on the string to delimit this into an array.
<cfset x = REMatch("<(.*?)>",list) />
This works fine, except that it also returns the angular brackets <> around the email address
x[1] = <[email address]>
Just for simplicity sake because the cfdocs are quite regex ambiguous, I wrote this loop to remove the first and last character of each index..
<cfloop from="1" to="#arrayLen(x)#" index="y">
<cfset a = #RemoveChars(x[y], 1, 1)# />
<cfset a = #left(a,len(a)-1)# />
<cfset x[y] = a />
</cfloop>
This works fine, yay, I have my array now.
However, it's not what I wanted. How can I return the email address WITHOUT the angular brackets included in the first place?
(Please note I also tried REReplace and REFind only returns the index of the occurrance)
(Also note that there are no [] brackets in the string, that's just saying the value inside isn't what I posted here)
Coldfusion implements a regex flavor (Apache ORO, see this answer for details) that doesn't support lookbehind assertions which would be useful in this case.
But we can arrive at an approximation:
<cfset x = REMatch("[^<>]+(?=>)",list) />
should work as long as all angle brackets occur in unnested, balanced pairs.
Explanation:
[^<>]+ # Match one or more characters except angle brackets
(?=>) # Make sure the next character is a closing angle bracket
I'm struggling a bit with ColdFusion (not the language I ever write in).
I am trying to do a regex to get a part of a string.
So for example, if my string is: D_CECILA23_CEC23423
I want the part that is between the 2 underscores.
This is the code I have so far, and it works for anything that is alpha characters, but when a number is thrown into the mix, it just breaks.
<cfset myStr = "D_CELCI_LISA">
<cfset myStr2 = reReplace(myStr, "([\w\d\%]+)(\_)([/ A-Z]+)(\_)([\w\d\?]+)", "\3", "all") >
<cfoutput>
myStr: #myStr#<br />
myStr2: #myStr2#<br />
</cfoutput>
Which gives me:
myStr: D_CELCI_LISA
myStr2: CELCI
If it really is as simple as getting the text between the first and second underscore character, you don't need a regex. This'll do it:
myStr2 = listGetAt(myStr, 2, "_");
That said, this should do for the regex in that context: ^.*_([^_]+)_.*$, eg:
myStr2 = reReplace(myStr, "^.*_([^_]+)_.*$", "\1", "all");
#user2429578 ListLast() and ListFirst() for the last or first element of a list.
I am using a regular expression like
<cfset a = ReFind("DESCRIBE\+[^>]*>", myResult.Header, 1, true) />
If I need that this Regular Expression should not include DESCRIBE+ in calculating the LEN and Position values. How should I write it?
DESCRIBE+ is 9 characters, cant you just add / subtract this number and do math.
<cfset a = ReFind("DESCRIBE\+([^>]*>)", myResult.Header, 1, true) />
<cfif ArrayLen(a.pos) GT 1><!--- match found! --->
<cfset afterDescribePosition = a.pos[2]>
<cfset afterDescribeLength = a.len[2]>
</cfif>
ReFind (when the fourth param is set to true, as you have done) will return a structure with two values (pos and len). Each of these is an array. If you don't have any capture groups ( parenthesis) within your regex, then both of these arrays will be just one value long - representing the full regex match. If you have capture groups defined (as I do in my example), then the subsequent values in each array will correspond with the respective capture group. In my example, there is only one capture group, so each array will be of length 2 (assuming there is a match). The values at the second position will therefore relate to the first capture group.
ReFind
If ColdFusion supports look behind, then you can use (?<=DESCRIBE\+)[^>]*>
I have the following:
<dd>
<select id="contactLocation" name="contactLocation" size="1">
<option value="Online"<cfif attributes.contactLocation eq "Online">selected</cfif>>Online</option>
<cfoutput query="storeLocations">
<option value="#storeLocations.name#"<cfif attributes.contactLocation eq "#storeLocations.name#">selected</cfif>>#storeLocations.state# - #storeLocations.city#, #left(storeLocations.storeID, 3)#</option>
</cfoutput>
</select>
I added the two top cfset variables as I was trying to figure it out. The string in the database returns 111/NAME and I want to remove the forward slash and everything else to the right of it.
Currently with the two variables I added it just returns the first 3 characters but it is only displaying the one row for every single item in the drop down.
How do I remove the forward slash and everything to the right of it within #storeLocations.storeID#
UPDATE:
Actually Now I have it display all 3 characters per row but what if there are only 2 or if there are 4? I am close I just need the last part.
If the separator is ALWAYS a "/" character and the "/" character will not appear in either token, think of this value as a list with a "/" delimiter and just get the last element with listLast:
listLast(storeLocations.storeID, "/")
If the 2nd part could have a "/" in it, but the first part never will, because its a number, then you can just get rid of the first token using listRest:
listRest(storeLocations.storeID, "/")
Edit: Since I can't tell my right from my left...
listFirst(storeLocations.storeID, "/")