Last active
June 13, 2018 11:52
-
-
Save pjdietz/5292681 to your computer and use it in GitHub Desktop.
Construct a PHP comparison function for use in usort() given an array of comparion functions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Given an ordered array of comparison functions, return one function that | |
* starts with the first and uses the subsequent functions in order in the | |
* event of equal items. | |
* | |
* @param $sortFnArr | |
* @param int $index | |
* @return callable | |
* @throws \Exception | |
*/ | |
function makeComplexSortFunction($sortFnArr, $index = 0) | |
{ | |
if (isset($sortFnArr[$index])) { | |
$fn1 = $sortFnArr[$index]; | |
} else { | |
throw new Exception('First argument must be an array conatining at least one callable'); | |
} | |
$fn2 = null; | |
if (isset($sortFnArr[$index + 1])) { | |
$fn2 = makeComplexSortFunction($sortFnArr, $index + 1); | |
} | |
return makeChainedSortFunction($fn1, $fn2); | |
} | |
/** | |
* Given two comparison functions, return a comparison function that uses | |
* the first unless it evaluates as equal, then uses the second. | |
* | |
* @param $fn1 | |
* @param $fn2 | |
* @return callable | |
*/ | |
function makeChainedSortFunction($fn1, $fn2) | |
{ | |
if (!is_callable($fn2)) { | |
return $fn1; | |
} | |
return function ($a, $b) use ($fn1, $fn2) { | |
$comp = $fn1($a, $b); | |
if ($comp !== 0) { | |
return $comp; | |
} | |
return $fn2($a, $b); | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// 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' | |
) | |
); | |
// Arrange some sort functions (defined below) in a partiular order in an array. | |
// Pass that array to makeComplexSortFunction() to build the complex sort function. | |
// Use this complex function with usort() to sort the data. | |
$sortArrays = array('compareFirstName', 'compareAge', 'compareColor'); | |
$complexFn = 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 = 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 | |
// Some comare 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; | |
} | |
/** | |
* Given an ordered array of comparison functions, return one function that | |
* starts with the first and uses the subsequent functions in order in the | |
* event of equal items. | |
* | |
* @param $sortFnArr | |
* @param int $index | |
* @return callable | |
* @throws \Exception | |
*/ | |
function makeComplexSortFunction($sortFnArr, $index = 0) | |
{ | |
if (isset($sortFnArr[$index])) { | |
$fn1 = $sortFnArr[$index]; | |
} else { | |
throw new Exception('First argument must be an array conatining at least one callable'); | |
} | |
$fn2 = null; | |
if (isset($sortFnArr[$index + 1])) { | |
$fn2 = makeComplexSortFunction($sortFnArr, $index + 1); | |
} | |
return makeChainedSortFunction($fn1, $fn2); | |
} | |
/** | |
* Given two comparison functions, return a comparison function that uses | |
* the first unless it evaluates as equal, then uses the second. | |
* | |
* @param $fn1 | |
* @param $fn2 | |
* @return callable | |
*/ | |
function makeChainedSortFunction($fn1, $fn2) | |
{ | |
if (!is_callable($fn2)) { | |
return $fn1; | |
} | |
return function ($a, $b) use ($fn1, $fn2) { | |
$comp = $fn1($a, $b); | |
if ($comp !== 0) { | |
return $comp; | |
} | |
return $fn2($a, $b); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment