In the vein of my last post on ColdFusion 10’s new ArrayEach() and StructEach() functions, there are some other related functions that help with the very common task of filtering arrays, structs, and list. The new functions are ArrayFilter(), ListFilter(), and StructFilter().

Like ArrayEach() and StructEach(), the new filter methods have a “function” parameter (which can also be either an inline function or a named function). However, unlike ArrayEach() and StructEach() which return nothing, the new filter functions return a new array, list, or struct, respectively.

To accomplish this, you need to return a boolean from the function parameter. If the current array element, list item, or structure value matches some criteria and returns “true”, it will be added to the new returned array/list/structure. Conversely, if it fails the criteria and returns “false,” it will be excluded from what is returned.

NOTE:  The array/list/struct filter() functions return NEW arrays/lists/structures. The original arrays/lists/structs against which the filter() functions are called are unaffected.

An Example

Let’s say that we have a simple set of “circles” for a Google+ account which includes a circle for friends, one for co-workers, and another for family. We might model this data like so:

'circles' = {
    'friends': ['Lucas','Phil','Dave','Brian','Dillon'],
    'coworkers': ['Tyler','Mike','Doug'],
    'family': ['Dean','Jared','Jason']
};

Now, let’s imagine that for some reason, we want to filter all of the people in our circles, and return all the contacts (regardless of circle) whose names start with the letter “D”.  One approach might be as so:

// create an array to hold all the names
allDnames = [];
// use structeach() to evaluate each "circle" 
structeach(circles,function(key,value) {
     // "matched" names will be the new array returned from the arrayfilter()
     // which is applied to each circle in the structeach() loop
     matchednames = arrayfilter(value,function(obj) {
         // if the first letter is a "D", return true; otherwise, return false;
         return left(obj,1)=='D';
     });
     // now let's add each filtered name to our master array of "D" names 
     arrayeach(matchednames,function(obj) {
          arrayappend(allDnames,obj);
     });
});

See the live example or grab the code from GitHub

Wrapping Up

As you can see, using CF10’s new ArrayFilter() function is pretty simple, and the ListFilter() and StructFilter() functions work exactly the same, just with slightly different parameters and return types.

But perhaps more importantly, this example shows how functions like StructEach() and ArrayFilter() can make processing of complex data structures a snap. Instead of bothering with messy for-loops in which it would be incredibly easy to lose our place, this approach feels much more sane and easy to follow.