Reputation: 1753
I have an array of people's names:
Array
(
[1] => A. Aitken
[2] => A. C. Skinner
[3] => A. Chen
[4] => R. Baxter
)
What's the quickest way to sort the array in (alphabetical) order of the surname in php? i.e. to give
Array
(
[1] => A. Aitken
[4] => R. Baxter
[3] => A. Chen
[2] => A. C. Skinner
)
Upvotes: -1
Views: 1327
Reputation: 48071
Because it is not performant to call two or more functions on each iteration of uasort()
AND because array_multisort()
will not preserve numeric keys, I have devised a script to minimize iterated function calls and separately preserve keys while using array_multisort()
.
Code: (Demo)
$firsts = [];
$lasts = [];
$keys = [];
foreach ($array as $keys[] => $v) {
[$firsts[], $lasts[]] = preg_split('/.*\K |^/', $v);
}
array_multisort($lasts, $firsts, $keys, $array);
var_export(array_combine($keys, $array));
The above script populates separate (equally sized) arrays for first names, last names and original keys.
The regular expression splits on the last occurring space OR if that doesn't exist, it splits on the position before the first character (meaning the first name value will be blank).
array_multisort()
will sort by last names ASC, then first names ASC, then keys ASC (but by this point there will be no ties to break), then the full name values ASC (but again, there will be no ties to break).
array_combine()
is called to re-associate the keys with their original values in their new positions.
Upvotes: 0
Reputation: 17817
You can sort using decorate-sort-undecorate pattern by key being last element of array that is result of splitting your string with spaces
$arr = array(
'A. Aitken',
'A. C. Skinner',
'A. Chen',
'R. Baxter'
);
// actual sorting below
$arr= array_map(create_function('$a', 'return array(array_slice(explode(" ", $a), -1), $a);'), $arr); // transform into array of arrays consisted of sort key and item
sort($arr); // sort array of arrays
$arr = array_map('end', $arr); // take only last element from each array
print_r($arr);
Upvotes: 1
Reputation: 47114
Have a look at uksort and the example given there, which is very similar to your problem.
You may want to replace the regexps there with
preg_replace("/[A-Z]\\. /", '', $a);
Upvotes: 3
Reputation: 8382
function cmp($a, $b)
{
$a1 = explode(' ', $a);
$b1 = explode(' ', $b);
return strcasecmp(end($a1), end($b1));
}
usort($arr, 'cmp');
Upvotes: 5