Utility Function: PatternExtract()

Yet another Pattern based utility function. PatternExtract() takes a pattern and gives you make a structure with values based on the groups. Additional function arguments (beyond pattern and string) are used to determine the keys (in order) that match with the groups.

<cffunction name="PatternExtract" output="false" returntype="struct">
    <cfargument name="pattern" type="string" required="true" />
    <cfargument name="string" type="string" required="true" />

    <cfset var returnValue = StructNew() />
    <cfset var array = Duplicate(arguments) />

    <cfset ArrayDeleteAt(array, 1) />
    <cfset ArrayDeleteAt(array, 2) />

    <cfif IsSimpleValue(arguments.pattern)>
        <cfset arguments.pattern = CreateObject("java", "java.util.regex.Pattern").compile(arguments.pattern) />
    </cfif>
    
    <cfset local.matcher = arguments.pattern.matcher(arguments.string)>

    <cfif local.matcher.matches()>
        <cfset local.groups = local.matcher.groupCount() />
        <cfloop from="1" to="#local.groups#" index="x">
            <cfset returnValue[array[x]] = local.matcher.group(x) />
        </cfloop>
    </cfif>

    <cfreturn returnValue />
</cffunction>

I coded this in a hurry, so yeah its a little sloppy. I'll try and update this post with a more refined version.

 

Utility Function: QueryAddRowData()

This one probably isn't original, but I wanted to be able to add whole rows to query sets in a simple manner. The built in functions let you add new columns in a simple way, but not new rows. Thats kind of weird, since I'd think that people would want to add rows more often the columns. QueryAddRowData() is designed to be flexible in its allowed inputs, working with structs, arrays, and lists.

<cffunction name="QueryAddRowData" access="public" output="false" returntype="void">
    <cfargument name="query" type="query" required="true" />
    <cfargument name="data" type="any" required="true" />
    <cfargument name="delimiter" type="string" required="false" default="," />
    
    <cfset var local = StructNew() />
    
    <cfif NOT (IsArray(arguments.data) OR (IsStruct(arguments.data) AND NOT isObject(arguments.data)) OR IsSimpleValue(arguments.data))>
        <cfthrow errorcode="QueryAddRowData" message="Invalid data for argument data. Valid types are array, struct, and string." />
    </cfif>
    
    <cfset QueryAddRow(arguments.query) />
    
    <cfif IsArray(arguments.data)>
        <cfset local.columns = ListToArray(arguments.query.columnList) />
        <cfloop from="1" to="#ArrayLen(local.columns)#" index="x">
            <cfset QuerySetCell(arguments.query, local.columns[x], arguments.data[x]) />
        </cfloop>    
        
    <cfelseif IsStruct(arguments.data) AND NOT isObject(arguments.data)>
        <cfloop collection="#arguments.data#" item="column">
            <cfset QuerySetCell(arguments.query, column, arguments.data[column]) />
        </cfloop>
    <cfelseif IsSimpleValue(arguments.data)>
        <cfset local.data = ListToArray(arguments.data, arguments.delimiter) />
        <cfset local.columns = ListToArray(arguments.query.columnList) />
        <cfloop from="1" to="#ArrayLen(local.columns)#" index="x">
            <cfset QuerySetCell(arguments.query, local.columns[x], local.data[x]) />
        </cfloop>    
    </cfif>
    
    <cfreturn />
</cffunction>

Please note that with arrays and lists, the data must be ordered as it would be in the Query.columnList (alphabetically).

 

Utility Function: IsTime()

My company often splits up date and time entries on forms, and then concatenates them back together on the back end. This is fine, except the time inputs are prone to errors, as IsDate() seems to be the only built in check to see if a string is a time, and it matches on things that are not purely times. To get around this, I create a new check: IsTime().

 

Utility Function: Singularize()

Well, after doing pluralize(), it should be no surprise that I also wanted to do singularize(). There are actually more rules for this one, even though I tried harder to make the rules smarter, rather then more numerous. In the end, the code is identical, save for the different list of patterns to match. Again, these patterns are based on the singularization regular expressions I found on ThinkSharp.org, although with my own modifications. Read more to see the code and the results of testing.

 

Utility Function: Pluralize()

So, I've been putting up a bunch of functions to work with Java patterns, especially working with groups. Now its time to put some of them to work to make a function to handle pluralization. Pluralizing arbitrary strings is important in dynamic systems, and used heavily in some ORM schemes, so I thought I'd try to make one. My first version is based on pluralization regular expressions found at ThinkSharp, although I've made some modifications and changes to make the substitutions more dynamic, and preventing pluralization rules from altering a word that already appears to be pluralized. Click more to check out the code and the tests.

 

Utility Function: PatternReplace()

Ok, so this one is neat. It takes a pattern and a string, extracts the groups, and then injects the groups into a replacement string based on group numbers. The notation "$x" is used to indicate replacement position, where x is the group number you want to use. The neat thing is that position 0 always corresponds to the whole original string.


<cffunction name="PatternReplace" output="false" returntype="string">
    <cfargument name="pattern" type="string" required="true" />
    <cfargument name="string" type="string" required="true" />
    <cfargument name="replacement" type="string" required="true" />
    
    <cfset var local = StructNew() />
    
    <cfif IsSimpleValue(arguments.pattern)>
        <cfset arguments.pattern = CreateObject("java", "java.util.regex.Pattern").compile(arguments.pattern) />
    </cfif>
    
    <cfset local.matcher = arguments.pattern.matcher(arguments.string) >
    
    <cfreturn local.matcher.replaceAll(arguments.replacement) />
</cffunction>

Example:


<!--- This results in "google dog" --->
<cfset x = PatternReplace("d(o)(g)", "dog", "$2$1$1$2le $0") />

 

More Entries

Jon Hartmann, July 2011

I'm Jon Hartmann and I'm a Javascript fanatic, UX/UI evangelist and former ColdFusion master. I blog about mysterious error messages, user interface design questions, and all things baffling and irksome about programming for the web.

Learn more about me on LinkedIn.