note 109493 deleted from function.usort by danbrown
| From: | danbrown@php.net | Date: | Mon, 30 Jul 2012 15:58:09 +0000 |
| Subject: | note 109493 deleted from function.usort by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-189509@lists.php.net to get a copy of this message | ||
Note Submitter: vos
----
Jian Wu, actually your code doesn't preserve the original order. It works for arrays with few
entries, but if you try it for, say, array of 9 objects, you can see that the order is random no
matter 0 or 1 you return when values are equal.
I needed a way to make usort() key-preserving, and came up with the most straight-forward way: when
the values are equal, we additionally compare the keys.
Unfortunately, usort()'s $callback function doesn't have parameters for keys, and
array_search() is slow, so I used uksort() for that.
(my goal was to sort a list of strings by number of '/'es in them)
<?php
$urls = [
'url://somehost/',
'url://somehost/1.htm',
'url://somehost/2_dir/',
'url://somehost/3.htm',
'url://somehost/dir_4/',
'url://somehost/dir_4/subdir/',
'url://somehost/2_dir/file.txt',
];
uksort($urls, function ($a, $b) use ($urls) {
$countA = substr_count($urls[$a], '/');
$countB = substr_count($urls[$b], '/');
if ($countA != $countB) {
return $countA - $countB;
} else {
return $a - $b;
}
});
print_r($urls);
?>
output:
Array
(
[0] => url://somehost/
[1] => url://somehost/1.htm
[3] => url://somehost/3.htm
[2] => url://somehost/2_dir/
[4] => url://somehost/dir_4/
[6] => url://somehost/2_dir/file.txt
[5] => url://somehost/dir_4/subdir/
)
(as you can spot, uksort() preserves the keys, so if you want straight 0..N keys, you can use
array_values())