You can not directly order a part of an array. You can only divide your array into the parts you want to sort, then sort the parts, and then apply that sort on the array data. Because you can not change the positions of the keys as well. As Tim Lytle suggested, get the keys, sort them, then you have the solution. This reduces the problem a bit.
Naturally there is a solution for it. However, keep in mind that your data-structure is pretty awkward to sort. I did the following:
- Get the keys
- Categorize the keys: The category is the key itself if does not contain a number or it's the number if it contains a number.
- Divide all keys into groups based on categories. That means, each time the category changes, a new group starts:
ALPHA, DIGIT, ALPHA
in your case.
- Got through all groups and handle them.
DIGIT
groups might need sorting, so I sorted them (e.g. if agepartner
comes before partner
, I just did a a-z sort + reverse).
- Flatten all parts into a key-array again. Key-sorting done.
- Create a
$sorted
array based on the new key-order and the values from the original array.
In case you need to sort the numbers (e.g. first 1, then 2), you can sort each DIGIT
group as well by key-sorting (ksort
) the inner array. As your data-structure is that complex, the following code-example is with debug output and some comments, so it's at least a little bit easier for you to go through and to play with it:
$array = array ('project'=>'My project','leader'=>'Michael Phepps','partner1'=>'John Campbell','partner2'=>'Phillip Prescott','agepartner1'=>25, 'agepartner2'=>'44', 'budget'=>'80000');
// reduce the problem: If we can sort the keys, we have the solution.
$keys = array_keys($array);
echo "Keys:\n";
var_dump($keys);
// categorize keys: alpha-only or alpha and digits at the end
$categories = array();
foreach($keys as $key)
{
$r = preg_match('/^([a-z]+)(\d*)$/', $key, $matches);
assert('$r !== FALSE');
list(,$alpha, $digits) = $matches;
$category = $digits ? $digits : $alpha;
$categories[$category][] = $key;
}
echo "Categories:\n";
var_dump($categories);
// group categories together in their order: ALPHA blocks and DIGIT blocks
define('GROUP_ALPHA', 1);
define('GROUP_DIGIT', 2);
$last = GROUP_ALPHA;
$group = array(); // start with an empty group to add to, pointer
$groups = array(array(GROUP_ALPHA => &$group));
foreach($categories as $vkey => $category)
{
$current = is_int($vkey) ? GROUP_DIGIT : GROUP_ALPHA;
if ($current != $last)
{
// add new group
unset($group);
$group = array();
$groups[] = array($current => &$group);
}
$group[] = $category;
$last = $current;
}
unset($group); // remove pointer
echo "Groups:\n";
var_dump($groups);
// sort and flatten groups
$ungroup = array();
foreach($groups as $type => $group)
{
if ($type == GROUP_DIGIT)
{
// if digit groups need to be sorted: partner, agepartner
foreach($group as &$items)
{
sort($items);
array_reverse($items);
unset($items);
}
}
// flatten the group
$group = call_user_func_array('array_merge', $group);
$group = call_user_func_array('array_merge', $group);
$ungroup = array_merge($ungroup, $group);
}
echo "Un-Grouped:\n";
var_dump($ungroup);
// solve
$sorted = array();
foreach($ungroup as $key)
{
$sorted[$key] = $array[$key];
}
echo "Sorted:\n";
var_dump($sorted);
Output:
Keys:
array(7) {
[0]=>
string(7) "project"
[1]=>
string(6) "leader"
[2]=>
string(8) "partner1"
[3]=>
string(8) "partner2"
[4]=>
string(11) "agepartner1"
[5]=>
string(11) "agepartner2"
[6]=>
string(6) "budget"
}
Categories:
array(5) {
["project"]=>
array(1) {
[0]=>
string(7) "project"
}
["leader"]=>
array(1) {
[0]=>
string(6) "leader"
}
[1]=>
array(2) {
[0]=>
string(8) "partner1"
[1]=>
string(11) "agepartner1"
}
[2]=>
array(2) {
[0]=>
string(8) "partner2"
[1]=>
string(11) "agepartner2"
}
["budget"]=>
array(1) {
[0]=>
string(6) "budget"
}
}
Groups:
array(3) {
[0]=>
array(1) {
[1]=>
array(2) {
[0]=>
array(1) {
[0]=>
string(7) "project"
}
[1]=>
array(1) {
[0]=>
string(6) "leader"
}
}
}
[1]=>
array(1) {
[2]=>
array(2) {
[0]=>
array(2) {
[0]=>
string(8) "partner1"
[1]=>
string(11) "agepartner1"
}
[1]=>
array(2) {
[0]=>
string(8) "partner2"
[1]=>
string(11) "agepartner2"
}
}
}
[2]=>
array(1) {
[1]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(6) "budget"
}
}
}
}
Un-Grouped:
array(7) {
[0]=>
string(7) "project"
[1]=>
string(6) "leader"
[2]=>
string(8) "partner1"
[3]=>
string(11) "agepartner1"
[4]=>
string(8) "partner2"
[5]=>
string(11) "agepartner2"
[6]=>
string(6) "budget"
}
Sorted:
array(7) {
["project"]=>
string(10) "My project"
["leader"]=>
string(14) "Michael Phepps"
["partner1"]=>
string(13) "John Campbell"
["agepartner1"]=>
int(25)
["partner2"]=>
string(16) "Phillip Prescott"
["agepartner2"]=>
string(2) "44"
["budget"]=>
string(5) "80000"
}