|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2014-12-18 15:49 UTC] craig at craigfrancis dot co dot uk
Description: ------------ As hinted by example 3: http://php.net/array_multisort I find that I'm frequently sorting arrays by a particular key (admittedly not from the database, as that has the ORDER BY clause). This can be done with: function sort_name($a, $b) { return strnatcmp($a['name'], $b['name']); } uasort($data, 'sort_name'); Or perhaps with PHP 5.3 anonymous functions: uasort($data, function ($a, $b) { return strnatcmp($a['name'], $b['name']); }); But perhaps we could introduce a function that can reduce the amount of code required (making it easier to read): array_key_sort($data, 'name'); array_key_sort($data, 'name', SORT_STRING); The example implementation below uses a class, as unfortunately my code needs to run on a PHP 5.1 server (so no anonymous functions). Test script: --------------- function array_key_sort(&$array, $key, $type = 'numerical') { $array_key_sort = new array_key_sort($key); uasort($array, array($array_key_sort, $type)); } class array_key_sort { private $key = NULL; public function __construct($key) { $this->key = $key; } public function numerical($a, $b) { if ($a[$this->key] == $b[$this->key]) { return 0; } return ($a[$this->key] < $b[$this->key] ? -1 : 1); } public function strcmp($a, $b) { return strcmp($a[$this->key], $b[$this->key]); } public function strcasecmp($a, $b) { return strcasecmp($a[$this->key], $b[$this->key]); } public function strnatcmp($a, $b) { return strnatcmp($a[$this->key], $b[$this->key]); } public function strnatcasecmp($a, $b) { return strnatcasecmp($a[$this->key], $b[$this->key]); } } PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 06:00:01 2025 UTC |
I can generalize this pattern into two functions; here is an example: <?php $f = function(callable $select, callable $f) { return function(...$args) use($select, $f) { return $f(...array_map($f, $args)); }; }; function select_offset($offset) { return function($data) { return $data[$offset]; }; } $array = [ ['name' => 'Bob'], ['name' => 'Bird'], ]; uasort($array, $f('strnatcmp', select_offset('name'))); var_dump($array); ?> However, I genuinely think that writing it out explicitly is better: <?php uasort($array, function($a, $b) { return strnatcmp($a['name'], $b['name']); }); ?> Also note that any function we add won't help you on a PHP 5.1 system since it would not be backported.Here is a working example (PHP 5.3+) of what I posted in the last comment: <?php $f = function($f, $select) { return function() use($f, $select) { return call_user_func_array( $f, array_map($select, func_get_args()) ); }; }; function select_offset($offset) { return function($data) use($offset) { return $data[$offset]; }; } $array = array( array('name' => 'Bob'), array('name' => 'Bird'), ); uasort($array, $f('strnatcmp', select_offset('name'))); var_dump($array); ?>Fair enough... I just thought that this was a pretty common use case that it might be better to have a function that everyone could use. Says he remembering that I should have used the SORT_NUMERIC/NATURAL/STRING/REGULAR constants, as the function names are not particularly easy to remember (e.g. strnatcasecmp). -------------------------------------------------- <?php function array_key_sort(&$array, $key, $sort_flags = SORT_STRING, $sort_order = SORT_ASC) { $array_key_sort = new array_key_sort($key); switch ($sort_flags & ~SORT_FLAG_CASE) { // ref https://github.com/php/php-src/blob/master/ext/standard/array.c#L144 case SORT_NUMERIC: $type = 'numeric'; break; case SORT_NATURAL: $type = ($sort_flags & SORT_FLAG_CASE ? 'strnatcasecmp' : 'strnatcmp'); break; case SORT_STRING: case SORT_REGULAR: default: $type = ($sort_flags & SORT_FLAG_CASE ? 'strcasecmp' : 'strcmp'); break; } uasort($array, array($array_key_sort, $type)); if ($sort_order == SORT_DESC) { // Cannot merge type and order $array = array_reverse($array); } } if (!defined('SORT_NATURAL')) define('SORT_NATURAL', 6); // PHP 5.4+ if (!defined('SORT_FLAG_CASE')) define('SORT_FLAG_CASE', 8); class array_key_sort { private $key = NULL; public function __construct($key) { $this->key = $key; } public function strcmp($a, $b) { return strcmp($a[$this->key], $b[$this->key]); } public function strcasecmp($a, $b) { return strcasecmp($a[$this->key], $b[$this->key]); } public function strnatcmp($a, $b) { return strnatcmp($a[$this->key], $b[$this->key]); } public function strnatcasecmp($a, $b) { return strnatcasecmp($a[$this->key], $b[$this->key]); } public function numeric($a, $b) { if ($a[$this->key] == $b[$this->key]) { return 0; } return ($a[$this->key] < $b[$this->key] ? -1 : 1); } } ?> e.g. array_key_sort($results, 'score', SORT_NUMERIC, SORT_DESC); array_key_sort($products, 'sort', SORT_NUMERIC);