An array wrapper for functional programming
HTML ColdFusion JavaScript CSS
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
models
node_modules
testbox
tests
.travis.yml
LICENSE
ModuleConfig.cfc
README.md
box.json
gulpfile.js
package.json
server.json

README.md

CFCollection

An array wrapper for functional programming

Build Status

WireBox Integration

If your CFML engine supports static methods (Lucee 5+), WireBox will return a method with a static constructor and static macro support. 👍

A few mappings are provided out-of-the-box:

collection & collection@CFCollection

Injecting this will give you access to an instance of Collection. You can start with a new collection by using the collect function.

collect & collect@CFCollection

Injecting this will give you direct access to the collect method.

Methods

init

Create a new collection. Can accept a list, array, or query.

var collection = new Collection( [ 1, 2, 3, 4 ] );
// OR
var collection = Collection::make( [ 1, 2, 3, 4 ] );
// OR
var collection = wirebox.getInstance(
    name = "Collection",
    initArguments = { collection = [ 1, 2, 3, 4 ] }
);

toArray

Returns the value of the collection as an array.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.toArray();

// [ 1, 2, 3, 4 ]

collect

Returns the values passed in as a new collection. Useful in conjunction with DI containers.

var collection = new Collection();

collection.collect(  [ 1, 2, 3, 4 ] );

collection.toArray();

// [ 1, 2, 3, 4 ]

keys

Returns the keys of an object as a new collection.

collection.keys( { "A" = 1, "B" = 2, "C" = 3 } );

// [ "A", "B", "C" ]

values

Returns the values of an object as a new collection.

collection.values( { "A" = 1, "B" = 2, "C" = 3 } );

// [ 1, 2, 3 ]

each

Loops over each value in the collection.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.each( function( item ) {
    writeOutput( "Item is #item#. " );
} );

// Item is 1. Item is 2. Item is 3. Item is 4.

map

Creates a new collection by applying a projection function to each item in the collection.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.map( function( item ) {
    return item * 2
} );

// [ 2, 4, 6, 8 ]

flatMap

Creates a new collection by applying a projection function to each item in the collection and then flattening the collection by one level.

var collection = new Collection( [ { x = 1, y = 2 }, { x = 1, y = 3 } ] );

collection.flatMap( function( point ) {
    return [ point.x, point.y ];
} );

// [ 1, 2, 1, 3 ]

flatten

Flattens a multi-dimensional array. It can accept a number of levels to flatten, or it flattens all levels by default.

var collection = new Collection( [ [ 1, 2, 3 ], [ 4, [ 5, 6 ] ], [ 7 ] ] );

collection.flatten();

// [ 1, 2, 3, 4, 5, 6, 7 ]

pluck

Shortuct for map to one or more keys on a struct or component. Keys can be passed in as a comma-separated list or an array.

var collection = new Collection( [
    { label = "A", value = 1 },
    { label = "B", value = 2 },
    { label = "C", value = 3 },
    { label = "D", value = 4 }
] );

collection.pluck( "value" );

// [ 1, 2, 3, 4 ]

filter

Returns a new collection where the predicate function provided returns true.

var collection = new Collection( [
    { label = "A", value = 1 },
    { label = "B", value = 2 },
    { label = "C", value = 3 },
    { label = "D", value = 4 }
] );

collection.filter( function( item ) {
    return item.value % 2 == 0;
} );

// [
//     { label = "B", value = 2 },
//     { label = "D", value = 4 }
// ]

unique

Returns a new collection with only unique items. The first unique item is used. Key order is not guaranteed. If no arguments are provided, a simple array is assumed. If a string value is provided, the value of that column in each array item is used as the unique key. A closure can be provided to have complete control over the unique key used.

var collection = new Collection( [ 1, 2, 1, 1, 1, 5, 5, 3, 4 ] );

collection.unique();

// [ 1, 2, 5, 3, 4 ]
var collection = new Collection( [
    { label = "A", value = 4 },
    { label = "B", value = 2 },
    { label = "A", value = 3 },
    { label = "A", value = 1 }
] );

collection.unique( "label" );
// SAME AS
collection.unique( function( item ) {
    return item.label;
} );

// [
//     { label = "A", value = 4 },
//     { label = "B", value = 2 }
// ]

reverse

Reverses the order of the collection.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.reverse();

// [ 4, 3, 2, 1 ]

zip

Combines the values from two arrays in to a tuple. It can optionally accept a projection function to influence the result returned.

var collection = new Collection( [ 1, 2, 3 ] );

collection.zip( [ 4, 5, 6 ] );

// [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ];

transpose

Transposes the values in a multi-dimensional array. Useful for array form inputs (like name[]).

var collection = new Collection( [
    [ "James T. Kirk", "Spock", "Odo", "Jonathan Archer" ],
    [ "Captain", "Commander", "Constable", "Captain" ],
    [ "Human", "Vulcan", "Changeling", "Human" ]
] );

collection.transpose();

// [
//     [ "James T. Kirk", "Captain", "Human" ],
//     [ "Spock", "Commander", "Vulcan" ],
//     [ "Odo", "Constable", "Changeling" ],
//     [ "Jonathan Archer", "Captain", "Human" ]
// ]

sort

Sorts the collection. Uses a simple compare if no callback function is provided. Can also accept a single string key to compare simple structs.

var collection = new Collection( [
    { label = "B", value = 2 },
    { label = "D", value = 4 },
    { label = "C", value = 3 },
    { label = "A", value = 1 }
] );

collection.sort( function( item1, item2 ) {
    return compare( item1.value, item2.value );
} );
// SAME AS
collection.sort( "value" );

// [
//     { label = "A", value = 1 },
//     { label = "B", value = 2 },
//     { label = "C", value = 3 },
//     { label = "D", value = 4 }
// ]

merge

Returns a new collection with the values of another array or Collection added to it.

var collection = new Collection( [ 1, 2, 3, 4 ] );
var anotherCollection = new Collection( [ 5, 6, 7, 8 ] );

collection.merge( anotherCollection );

// [ 1, 2, 3, 4, 5, 6, 7, 8 ]

slice

Returns a subset of the collection, starting at the given index and going either to the end of the collection or for the specified number of items.

var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.slice( 2, 3 );
// SAME AS
collection.slice( 2 );

// [ 2, 3, 4 ]

chunk

Breaks a collection up in to chunks with the specified length.

var collection = new models.Collection( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] );

collection.chunk( 3 );

// [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]

where

Shortcut for filter. Accepts a key and value to filter down the collection by. value can be a single value, a list, or an array of values where the collection value can match any of the values provided.

var collection = new models.Collection( [
    { id = 1, name = "James T. Kirk", rank = "Captain", species = "Human" },
    { id = 2, name = "Spock", rank = "Commander", species = "Vulcan" },
    { id = 3, name = "Odo", rank = "Constable", species = "Changeling" },
    { id = 4, name = "Jonathan Archer", rank = "Captain", species = "Human" }
] );

collection.where( "species", "Human" );

// [
//     { id = 1, name = "James T. Kirk", rank = "Captain", species = "Human" },
//     { id = 4, name = "Jonathan Archer", rank = "Captain", species = "Human" }
// ];

var collection = new models.Collection( data );

expect( collection.toArray() ).toBe( expected );

empty

Returns whether the collection is empty.

var collection = new models.Collection();

collection.empty();

// true

first

Returns the first element in the collection. Can optionally accept a predicate function which will then return the first element that returns true from the predicate function. Can also accept a default value to use when the collection is either empty or no element satisfies the predicate function.

var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.first();

// 1
var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.first( function( num ) {
    return num > 4;
}, 5 );

// 5

last

Returns the last element in the collection. Can optionally accept a predicate function which will then return the last element that returns true from the predicate function. Can also accept a default value to use when the collection is either empty or no element satisfies the predicate function.

var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.last();

// 4
var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.last( function( num ) {
    return num > 2;
}, 5 );

// 4

count

Returns the number of elements in the collection.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.count();

// 4

length

Alias for count. Returns the number of elements in the collection.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.length();

// 4

size

Alias for count. Returns the number of elements in the collection.

var collection = new Collection( [ 1, 2, 3, 4 ] );

collection.size();

// 4

reduce

Applies a function against an accumulator and each value of the collection. The default value of the accumulator is the first value of the collection.

var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.reduce( function( acc, num ) {
    return acc + num;
}, 0 );

// 10

groupBy

Returns a struct where the keys are the value of the field passed in and the values are collection items that share the same value of the given key.

var collection = new models.Collection( [
    { id = 1, name = "James T. Kirk", rank = "Captain", species = "Human" },
    { id = 2, name = "Spock", rank = "Commander", species = "Vulcan" },
    { id = 3, name = "Odo", rank = "Constable", species = "Changeling" },
    { id = 4, name = "Jonathan Archer", rank = "Captain", species = "Human" }
] );

collection.groupBy( "rank" );

// {
//     "Captain" = [
//         { id = 1, name = "James T. Kirk", rank = "Captain", species = "Human" },
//         { id = 4, name = "Jonathan Archer", rank = "Captain", species = "Human" }
//     ],
//     "Commander" = [
//         { id = 2, name = "Spock", rank = "Commander", species = "Vulcan" },
//     ],
//     "Constable" = [
//         { id = 3, name = "Odo", rank = "Constable", species = "Changeling" }
//     ]
// }

serialize

Returns the underlying collection serialized to JSON. Can limit the serialized properties to a passed in comma-separated list or array of keys.

var collection = new models.Collection( [
    { label = "A", value = 1, importance = "10" },
    { label = "B", value = 2, importance = "20" },
    { label = "C", value = 3, importance = "50" },
    { label = "D", value = 4, importance = "20" }
] );

collection.serialize( [ "value", "importance" ] );

// [{"IMPORTANCE":10,"VALUE":1},{"IMPORTANCE":20,"VALUE":2},{"IMPORTANCE":50,"VALUE":3},{"IMPORTANCE":20,"VALUE":4}]

sum

Sums the values of a collection. Can accept an optional field to sum by.

var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.sum();

// 10
var collection = new models.Collection( [
    { label = "A", value = 1 },
    { label = "B", value = 2 },
    { label = "C", value = 3 },
    { label = "D", value = 4 }
] );

collection.sum( "value" );

// 10

avg

Averages the values of a collection. Can accept an optional field to average by.

var collection = new models.Collection( [ 1, 2, 3, 4 ] );

collection.sum();

// 2.5
var collection = new models.Collection( [
    { label = "A", value = 1 },
    { label = "B", value = 2 },
    { label = "C", value = 3 },
    { label = "D", value = 4 }
] );

collection.sum( "value" );

// 2.5

average

Alias for avg. Averages the values of a collection. Can accept an optional field to average by.

join

Joins the elements of a collection in to a string with a given delimiter.

var collection = new models.Collection( [ "Hello", "world" ] );

collection.join( ", " );

// "Hello, world"

pipe

Passes the collection in to the callback specified and returns the result returned from the callback. Allows for easier chaining of non-collection methods.

var scores = [ 96, 94, 85, 67, 55, 98, 72 ];
var collection = new models.Collection( scores );

function mapScoresToGrades( scores ) {
    return scores.map( function( score ) {
        if ( score >= 90 ) { return "A"; }
        else if ( score >= 80 ) { return "B"; }
        else if ( score >= 70 ) { return "C"; }
        else if ( score >= 66 ) { return "D"; }
        else { return "F"; }
    } );
}

collection.pipe( function( collection ) {
    return mapScoresToGrades( collection );
} );

// [ "A", "A", "B", "D", "F", "A", "C" ]

has

Returns true if any item in the collection returns true from the predicate function.

var collection = new models.Collection( [
    { id = 1, name = "James T. Kirk", rank = "Captain", species = "Human" },
    { id = 2, name = "Spock", rank = "Commander", species = "Vulcan" },
    { id = 3, name = "Odo", rank = "Constable", species = "Changeling" },
    { id = 4, name = "Jonathan Archer", rank = "Captain", species = "Human" }
] );

collection.has( function( crewMember ) {
    return crewMember.species == "Vulcan";
} );

// true

any

Alias for has. Returns true if any item in the collection returns true from the predicate function.

every

Returns true if every item in the collection returns true from the predicate function.

var collection = new models.Collection( [
    { id = 1, name = "James T. Kirk", rank = "Captain", species = "Human" },
    { id = 2, name = "Spock", rank = "Commander", species = "Vulcan" },
    { id = 3, name = "Odo", rank = "Constable", species = "Changeling" },
    { id = 4, name = "Jonathan Archer", rank = "Captain", species = "Human" }
] );

collection.every( function( crewMember ) {
    return crewMember.species == "Human";
} );

// false

Static Support

If your CFML engine supports static scopes and functions, you have some additional functionality available to you in the MacroableCollection component. This component will be returned by default if you are using WireBox.

make

Returns a new instance of the component. Syntactic sugar for new Collection

var collection = Collection::make( [ 1, 2, 3, 4 ] );

// [ 1, 2, 3, 4 ]

macro

Extends the functionality of every Collection instance with the new method. You have access to the current collection using the this keyword as well as any arguments passed in the function.

Collection::macro( "max", function() {
    if ( this.empty() ) {
        return 0;
    }

    var max = this.first();

    this.each( function( item ) {
        if ( item > max ) {
            max = item;
        }
    } );

    return max;
} );

var collection = Collection::make( [ 4, 4, 2, 6, 1, 3, 1 ] );

collection.max();

// 6