Created
May 11, 2012 17:33
-
-
Save leifwickland/2661205 to your computer and use it in GitHub Desktop.
sortBy() function for PHP (inspired by Scala)
This file contains 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 | |
/** | |
* Sorts an array based on keys provided by a closure which extracts a value from the array's elements. | |
* | |
* Keys are not preserved. The original is not modified. | |
* | |
* Inspired by Scala's Seq.sortBy() | |
* @see http://www.scala-lang.org/api/current/index.html#scala.collection.Seq | |
* | |
* @param $array array-like To sort. (Really it just needs to be something iterable.) | |
* @param $descendingOrder boolean Whether the keys should be sorted in ascending or descending order. | |
* @param $keyExtractor Closure Function that will be passed each element of $array to produce a key for sorting. Must return an int or string. | |
* | |
* @returns a new array sorted as you requested. | |
*/ | |
public static function sortBy($array, $descendingOrder, \Closure $keyExtractor) | |
{ | |
$newArray = array(); | |
foreach ($array as $value) { | |
$newArray[] = $value; | |
} | |
$descendingMultiplier = $descendingOrder ? -1 : 1; | |
$usortSucceeded = usort($newArray, function($a, $b) use ($descendingMultiplier, $keyExtractor) { | |
$aKey = $keyExtractor($a); | |
$bKey = $keyExtractor($b); | |
if (is_int($aKey) && is_int($bKey)) { | |
return $descendingMultiplier * (($aKey < $bKey) ? (-1) : (($aKey === $bKey) ? (0) : (1))); | |
} | |
if (is_string($aKey) && is_string($bKey)) { | |
return $descendingMultiplier * strcmp($aKey, $bKey); | |
} | |
throw new \Exception("keyExtractor must return an int or string."); | |
}); | |
if (!$usortSucceeded) { | |
throw new \Exception("Unable to sort array."); | |
} | |
return $newArray; | |
} | |
function testSortBy() { | |
$a = array( | |
2 => array('a' => 2), | |
1 => array('a' => 1), | |
0 => array('a' => 3), | |
); | |
$sorted = Framework::sortBy($a, false, function($e) { return $e['a']; }); | |
$this->assertTrue(is_array($sorted)); | |
$this->assertIdentical(count($sorted), count($a)); | |
$this->assertIdentical(reset($sorted), $a[1]); | |
$this->assertIdentical(next($sorted), $a[2]); | |
$this->assertIdentical(next($sorted), $a[0]); | |
} | |
function testSortByReverse() { | |
$a = array( | |
2 => array('a' => 2), | |
1 => array('a' => 1), | |
0 => array('a' => 3), | |
); | |
$sorted = Framework::sortBy($a, true, function($e) { return $e['a']; }); | |
$this->assertTrue(is_array($sorted)); | |
$this->assertIdentical(count($sorted), count($a)); | |
$this->assertIdentical(reset($sorted), $a[0]); | |
$this->assertIdentical(next($sorted), $a[2]); | |
$this->assertIdentical(next($sorted), $a[1]); | |
} | |
function testSortByDuplicateKeys() { | |
$a = array( | |
3 => array('a' => 2), | |
2 => array('a' => 2), | |
1 => array('a' => 1), | |
0 => array('a' => 3), | |
); | |
$sorted = Framework::sortBy($a, false, function($e) { return $e['a']; }); | |
$this->assertTrue(is_array($sorted)); | |
$this->assertIdentical(count($sorted), count($a)); | |
$this->assertIdentical(reset($sorted), $a[1]); | |
$this->assertIdentical(next($sorted), $a[3]); | |
$this->assertIdentical(next($sorted), $a[2]); | |
$this->assertIdentical(next($sorted), $a[0]); | |
} | |
function testSortByWithStringKeys() { | |
$a = array( | |
3 => array('a' => 'B'), | |
2 => array('a' => 'B'), | |
1 => array('a' => 'A'), | |
0 => array('a' => 'C'), | |
); | |
$sorted = Framework::sortBy($a, false, function($e) { return $e['a']; }); | |
$this->assertTrue(is_array($sorted)); | |
$this->assertIdentical(count($sorted), count($a)); | |
$this->assertIdentical(reset($sorted), $a[1]); | |
$this->assertIdentical(next($sorted), $a[3]); | |
$this->assertIdentical(next($sorted), $a[2]); | |
$this->assertIdentical(next($sorted), $a[0]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment