The Sorter
class is made for sorting records where each record is an associative array. For example, suppose $files
is an array of the following form :
$files[] = array( 'name' => 'fred.txt', 'ext' => 'txt', 'size' => 1234 ); $files[] = array( 'name' => 'jane.jpg', 'ext' => 'jpg', 'size' => 412 ); $files[] = array( 'name' => 'readme.txt', 'ext' => 'txt', 'size' => 592 );
You can sort by extension type and size as follows:
$sorter = new Sorter("ext,-size:n"); // sort by extension (alphabetic) and descending size $sorter->sort($files);
Basically it takes a comma separated list of field names (e.g. "region,city,area"
), each of which can optionally be preceded by a “+” (default) or “-” to say whether it is an ascending or descending sort and suffixed with a type letter (e.g “:n”) to say whether the sort is alphabetic (“s” and default), numeric (“n”) or by date (“d”). The date has to be in a format PHP recognises, but simple timestamps are numeric.
I think this should also work for arrays of numerically indexed arrays, so that "3,-2:d"
sorts by column 3 and then column 2 as a date descending, but I’ve not tested this.
the code
class Sorter { var $keys; function Sorter($keyspec) { $this->keys = $this->parseKeys($keyspec); } function sort( &amp;$arr ) { return usort( $arr, array($this,'compare') ); } function parseKeys($keyspec) { $keyspecs = explode(",",$keyspec); $keys = array(); foreach ( $keyspecs as $onespec ) { if ( $onespec{0} == '-' ) {< $onespec = substr($onespec,1); $dir = '-'; } else if ( $onespec{0} == '+' ) { $onespec = substr($onespec,1); $dir = '+'; } else { $dir = '+'; } $parts = explode(':',$onespec); if ( $parts[0] ) { switch ( $parts[1] ) { case 'i': case 'n': $type = 'n'; break; // number case 'd': $type = 'd'; break; // date case 's': default: $type = 's'; break; // string } $keys[] = array( $parts[0], $dir, $type ); } } return $keys; } function compare( $obj1, $obj2 ) { foreach( $this->keys as $key ) { list( $name, $dir, $type ) = $key; $fld1 = $obj1[$name]; $fld2 = $obj2[$name];< switch ( $type ) { case 'n': $cmp = $fld1 - $fld2; break; case 'd': $time1 = strtotime($fld1); $time2 = strtotime($fld2); if ( $time1 === false || $time1 === -1 || $time2 === false || $time2 === -1 ) { // false PHP 5.1, -1 older PHP $cmp = 0; // badly formed dates } else { $cmp = $time1 - $time2; } case 's': default: $cmp = strcmp($fld1,$fld2); break; } if ( $cmp == 0 ) continue; if ( $dir == '-' ) $cmp = - $cmp; return $cmp; } return 0; } }