Reputation: 3465
I have this array:
array ('project'=>'My project','leader'=>'Michael Phepps','partner1'=>'John Campbell','partner2'=>'Phillip Prescott','agepartner1'=>25, 'agepartner2'=>'44', 'budget'=>'80000');
The array is the result of some queries in diferent tables: project table fields: project, leader, budget. partners fields: partner, age
The order of the array is defined by an user, and executed like this:
foreach ($userarray as $field) {loadField($field)};
As the operation is for each field I obtain 'partner2' after 'partner1' but I need to get 'agepartner1' after 'partner1', because them are displayed in a html table after that.
Any suggestions can I obtain:
array ('project'=>'My project','leader'=>'Michael Phepps','partner1'=>'John Campbell', 'agepartner1'=>25, 'partner2'=>'Phillip Prescott', 'agepartner2'=>'44', 'budget'=>'80000');
Upvotes: 1
Views: 932
Reputation: 197682
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:
ALPHA, DIGIT, ALPHA
in your case.DIGIT
groups might need sorting, so I sorted them (e.g. if agepartner
comes before partner
, I just did a a-z sort + reverse).$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"
}
Upvotes: 0
Reputation: 17624
While perhaps not exactly the answer you're looking for, I think there may be a better way to approach your situation:
$data = array('key1' => 'is', 'key2' => 'test', 'key3' => 'This');
$order = array('key3', 'key1', 'key2');
foreach($order as $key){
print_r($data[$key]);
}
Output:
This is test.
So with your data:
$userarray = array ('project'=>'My project',
'leader'=>'Michael Phepps',
'partner1'=>'John Campbell',
'partner2'=>'Phillip Prescott',
'agepartner1'=>25,
'agepartner2'=>'44',
'budget'=>'80000');
$order = array('project',
'leader',
'partner1',
'agepartner1',
'partner2',
'agepartner2',
'budget');
foreach($order as $field) {
loadField($userarray[$field]);
}
Upvotes: 2