Chopping Off the End of a List

I’m sure there are tons of these functions around, but I decided to write my own.
The listChop function chops a list down to the specified size. Use it like this:

<cfset myList = "a,b,c,d,e"/>
<!--- Chop this list down to 3 elements. --->
<cfset myList = listChop(myList, 3[, delimiter])/>

Here’s the function:

<cffunction name="listChop" returnType="string" output="no" >
<cfargument name="targetList" type="string" required="true"/>
<cfargument name="amountToKeep" type="numeric" required="true"/>
<cfargument name="delimiter" type="string" required="false" default=","/>
<cfset var listSize = listLen(arguments.targetList, arguments.delimiter)/>
<cfset var i = 0/>
<cfif arguments.amountToKeep lt 0 or listSize - arguments.amountToKeep le 0>
<cfreturn arguments.targetList/>
</cfif>
<cfloop from="#arguments.amountToKeep+1#" to="#listSize#" index="i">
<cfset arguments.targetList = listDeleteAt(arguments.targetList,
arguments.amountToKeep+1,
arguments.delimiter)/>
</cfloop>
<cfreturn arguments.targetList/>
</cffunction>

I’m using it in a pretty big application I’m writing, so let me know if you see
any bugs.

7 Responses to Chopping Off the End of a List

  1. Tim Scaret says:

    You are right:http://www.cflib.org/udf.cfm?ID=605I think when you spend time writing your own functions when they already exist, and are readily available in a big library like cflib, you are wasting someone’s time, either your own, or (hopefully not), your employers/clients.It’s great to learn by doing, but I think in this case, writing your own function when one was readily available to you was counterproductive.

  2. It’s not that simple, Tim. I usually write my own UDFs and components even though I know there are hundreds available because:1. I like to know exactly how they work. Rather than download one that’s already written and going through it line by line, it’s often just as fast to write it myself.2. When I write my own UDFs and components, I get the API exactly how I want it.3. I can make my own UDFs and components leaner than generic code meant to work for as many people as possible in as many different circumstances as possible.4. My UDFs and components often leverage each other and are therefore more modular than generic code one might download.It’s a matter of resources. If I have time, I write my own (usually). If it’s something that will take minutes as opposed to days, I write my own (usually). It all depends on the specific case. It’s way too simple, however, to say uniformly that not using other people’s code is a waste of time.

  3. Tim Scaret says:

    Christian.You make some good points, sorry if I came off too neg on that post.

  4. Robby says:

    Sadly, it’s probably not going to look all that wonderful in the comments, but here’s another approach I threw together. Not highly tested and I’m aware that regex is considered slow, but when it’s compared to the array deleting elements in a loop, she might fair pretty wellEither way, food for thought.function test(list,count,delimit) {var regex = ”; var delim = ‘,’; // var’d statementsif (arraylen(arguments) gt 2)/*clean up delim to make sure there isn’t any special charactersrather harmless if it’s a comma, but a pipe delim (common) would kill itcould even be within it’s own udf.*/delim = rereplace(delimit,'(\+|\*|\?|\.|\[|\^|\$|\(|\)|\{|\||\\)’,’\\\1′);/*regex break down^ start of list(.*?#delim#){#count-1#} match all but the last element(.*?[^#delim#]){1} last element minus the delim(#delim#.*?)+ the rest of the list#delim#? incase there is a stray delim at the end$ end of string*/regex = ‘^((.*?#delim#){#count-1#}(.*?[^#delim#]){1})(#delim#.*?)+#delim#?$’;return rereplace(list,regex,’\1′);}

  5. here is another option that uses two functions: listLeft and arrayLeft. Again, we know the formatting will stink – but hopefully it is enough to be clear:function ListLeft(list, numElements){var delimiter=”,”;var array = ArrayNew(1);if (Arraylen(arguments) gt 2) {delimiter=arguments[3];}array = ListToArray(list,delimiter);array = arrayLeft(array,numElements);if(isArray(array))list = ArrayToList(array,delimiter);elselist = array;return list;}function ArrayLeft(array,numElements){var tArray= ArrayNew(1);if (numElements gte arrayLen(array)){return array;}for (i=1; i LTE numElements; i=i+1){tArray[i] = array[i];}return tArray;}when dealing with really long lists this seems to be faster. Before I rewrote them as two separate functions I did a little analysis which you can see here:http://rawlinson.us/blog/index.php?p=160I also have a bunch of other ones (listRight, arrayRight, listSplitLeft, arraySplitLeft, listDeleteLeft, listDeleteRight, arrayDeleteLeft, arrayDeleteRight if you need/want any of them.

  6. No worries, Tim. All opinions are always welcome!

  7. Alan says:

    The first response to this post stated that the UDF already existed. (http://www.cflib.org/udf.cfm?ID=605)I looked at it though, and it chops off a KNOWN number of elements from the end of a list.The one that was written as the subject of this post reduces a list of unknown length down to a known number of elements – two completely different functions. So this to me is a great example of looking at other people’s code, deciding if you can use it or not, or use parts of it, or just what you learned from it to write your own. Getting the CORRECT function into the code is worth your time, your client’s time, etc…