pjdietz/complex-sort

Chain multiple comare functions together for use in usort

v1.0.0 2013-08-19 16:30 UTC

README

ComplexSort allows you to chain together multiple comparison functions for us in PHP's usort function. For example, if you have a an array of associative arrays, each with the fields firstName, nickname, age, and favoriteColor, and you've created comparison functions to sort by each of these fields individually, you can use ComplexSort to build a new comparison function that combines these in whichever order you like.

Examples

Say way have this array:

// Here's some data.
$data = array(
    array(
        'firstName' => 'George',
        'nickname' => 'Geroge Sr.',
        'age' => 62,
        'favoriteColor' => 'orange'
    ),
    array(
        'firstName' => 'George',
        'nickname' => 'GOB',
        'age' => 42,
        'favoriteColor' => 'blue'
    ),
    array(
        'firstName' => 'George',
        'nickname' => 'George Michael',
        'age' => 16,
        'favoriteColor' => 'blue'
    ),
    array(
        'firstName' => 'Buster',
        'nickname' => 'Buster',
        'age' => 32,
        'favoriteColor' => 'violet'
    )
);

And suppose we have these functions for sorting individually:

// Some comparison functions. These aren't particular *good* ones, as they do
// nothing as far as checking if the array keys exist, but they'll work for
// this demo.

function compareFirstName($a, $b) {
    if ($a['firstName'] == $b['firstName']) {
        return 0;
    }
    return $a['firstName'] > $b['firstName'] ? 1 : -1;
}

function compareAge($a, $b) {
    if ($a['age'] == $b['age']) {
        return 0;
    }
    return $a['age'] > $b['age'] ? 1 : -1;
}

function compareColor($a, $b) {
    if ($a['favoriteColor'] == $b['favoriteColor']) {
        return 0;
    }
    return $a['favoriteColor'] > $b['favoriteColor'] ? 1 : -1;
}

We can make new comparison functions that order these individual functions in whichever order we need.

// Arrange some sort functions in a partiular order in an array.
// Pass that array to ComplexSort::makeComplexSortFunction() to combine them.
// Use this complex function with usort() to sort the data.
$sortArrays = array('compareFirstName', 'compareAge', 'compareColor');
$complexFn = ComplexSort::makeComplexSortFunction($sortArrays);
usort($data, $complexFn);

print "By firstName, age, favoriteColor: \n";
foreach ($data as $bluth) {
    print $bluth['nickname'] . "\n";
}

// By firstName, age, favoriteColor:
// Buster
// George Michael
// GOB
// Geroge Sr.

$sortArrays = array('compareColor', 'compareAge');
$complexFn = ComplexSort::makeComplexSortFunction($sortArrays);
usort($data, $complexFn);

print "By favoriteColor, age: \n";
foreach ($data as $bluth) {
    print $bluth['nickname'] . "\n";
}

// By favoriteColor, age:
// George Michael
// GOB
// Geroge Sr.
// Buster

Closures

The array passed to ComplexSort::makeComplexSortFunction() can include anything that is a callable in PHP. This means you can pass a string that names a function, or you can pass closures, like this:

$sort = ComplexSort::makeComplexSortFunction(array(
        function ($a, $b) {
            if ($a->orderTotal == $b->orderTotal) {
                return 0;
            }
            return $a->orderTotal > $b->orderTotal ? 1 : -1;
        },
        function ($a, $b) {
            if ($a->otherField == $b->otherField) {
                return 0;
            }
            return $a->otherField > $b->otherField ? 1 : -1;
        }
    ));
usort($data, $sort);

Install

Composer

Add an entry for "pjdietz/complex-sort" to your composer.json file's require property. If you are not already using Composer, create a file in your project called composer.json with the following content:

{
    "require": {
        "pjdietz/complex-sort": "1.*"
    }
}

Use Composer to download and install ComplexSort. Run these commands from the directory containing the composer.json file.

$ curl -s https://getcomposer.org/installer | php
$ php composer.phar install

You can now use ComplexSort by including the autoload.php file generated by Composer. vendor/autoload.php

Copy-and-paste

For a copy-and-paste version of the same functionality, see my original gist.

Happy sorting!