0

This should be fairly simple but my brain can't seem to process this at the moment. Hoping you can help :)

I have an array of posts that each have a tag, looks something like this:

Array(
   [0] = Array('Computers', postObject),
   [1] = Array('Sports', postObject),
   [2] = Array('Computers', postObject),
   [3] = Array('Business', postObject)
)

I was using asort() which seemed to sort the posts alphabetically, but I now need to sort the posts based on a specified order (stored in an array) that might have extra values.

Array(
   [0] = 'Sports',
   [1] = 'Fashion',
   [2] = 'Business',
   [3] = 'Computers',
   [4] = 'Stocks'
 )

I'm expecting the first array to be sorted like this:

Array(
   [0] = Array('Sports', postObject),
   [1] = Array('Business', postObject),
   [2] = Array('Computers', postObject),
   [3] = Array('Computers', postObject)
)

I don't think there is a simple php function to call, can you please advise ?

sirmdawg
  • 2,573
  • 3
  • 18
  • 32

2 Answers2

0

You can use the usort function, which sorts the array using a user-defined comparison function.

An untested solution can be:

$categories = array_flip($categories); // not needed by original solution
usort($posts, function($a, $b) use ($categories) {
    // original solution:
    // return array_search($a[0], $categories) > array_search($b[0], $categories);

    // shameless CAP (copy-and-paste) from Mike Brant's answer
    // actually, performs better, and I hope that he doesn't mind :)
    return $categories[$a[0]] > $categories[$b[0]];

});

This solution is applicable for PHP v >= 5.3, since it uses anonymous functions and closures

If you are using PHP < 5.3, you can use ksort function, like this (again, untested):

$new_arr = array();
$categories = array_flip($categories);
foreach ($posts as $post) {
    $new_arr[$categories[$post[0]]] = $post;
}
ksort($new_arr);
Stoic
  • 9,488
  • 5
  • 39
  • 60
  • "Provide context for links Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline." –  Dec 06 '13 at 20:06
  • @Stoic, the usort solution seems to be pretty close, for some reason it's still not following the correct order though – sirmdawg Dec 06 '13 at 20:13
  • Hmm, both of these solutions, your new one and mikes don't seem to order correctly :| – sirmdawg Dec 06 '13 at 20:18
  • are you sure? I just tested my original as well as the current code, and it seems to work correctly. `usort` updates the `$posts` variable itself (it uses by-reference passing of parameters) and therefore, your updated (sorted) array is available in `$posts` itself, after the above method. I am sure that you are aware about, but I can not think of any other reason. – Stoic Dec 06 '13 at 20:24
  • My bad, it was because of a case sensitive issue - nice work man! I had to add a bit of code to get it working, but you did solve what I asked :) – sirmdawg Dec 06 '13 at 20:27
  • For the record: `return array_search(strtolower($a[0]), array_map('strtolower', $orderArray)) > array_search(strtolower($b[0]), array_map('strtolower', $orderArray));` – sirmdawg Dec 06 '13 at 20:28
0

I would consider usort(). Example:

$array = array(...); // your multi-dimension array to sort
$sort_order_array = array(...); // your array defining sort order
$sort_order_array_flipped = array_flip($sort_order_array);

usort($array, function($a, $b) use ($sort_order_array_flipped) {
    return $sort_order_array_flipped[$a[0]] > $sort_order_array_flipped[$b[0]];
});

Note that I flipped the sort order array in able to make it easy to lookup the order value (0, 1, 2) based on the value stored in the main array. This is actually computationaly faster than doing a key loop with every iteration of usort()

Mike Brant
  • 66,858
  • 9
  • 86
  • 97