2

I have two simple arrays. One is an array of posts ($posts) and the other is an array of post ID's that should be on top of the stream, like they are featured ($featured). I am trying to find an efficient way to loop through them and if an ID is in both arrays, move it to the beginning of the $posts array, and the ones that are moved should be sorted ASC by $featured['order'], so for example, some posts ($posts):

Array
(
 [ab77] => Status_Update Object
 (
 [id] => ab77
 [title] => Status Update
 )
 [b4k7] => Status_Update Object
 (
 [id] => b4k7
 [title] => Status Update
 )
 [4d55] => Status_Update Object
 (
 [id] => 4d55
 [title] => Status Update
 )
 [13c5] => Status_Update Object
 (
 [id] => 13c5
 [title] => Status Update
 )
 [3aa2] => Status_Update Object
 (
 [id] => 3aa2
 [title] => Status Update
 )
)

and then some posts which should be featured ($featured):

Array
(
 [13c5] => Array
 (
 [id] => 13c5
 [order] => 1
 )
 [3a71] => Array
 (
 [id] => 3a71
 [order] => 2
 )
 [4d55] => Array
 (
 [id] => 4d55
 [order] => 3
 )
)

So the $posts array should end up sorted like this:

13c5 4d55 ab77 bk47 3aa2

How do I do this without a bunch of slow loops?

Barmar
787k57 gold badges553 silver badges666 bronze badges
asked Apr 27, 2015 at 21:46
6
  • It looks like you've got the ID as the array keys already, so you won't need nested loops - just one and inside you can check array_key_exists('13c5', $featured)) etc Commented Apr 27, 2015 at 21:51
  • If possible I would build the arrays out correctly in the first place. This will most likely be faster and elegant. It sounds like you want to create a new array of data from two existing queries. My suggestion is make a new query that give you the data you want instead of manipulating the existing data. This may not be best for your situation but in many cases it is. Commented Apr 27, 2015 at 21:51
  • Use uksort to sort using a user-written comparison function. The function should check whether both keys are in the featured array using array_key_exists. If they're both in or both not in, compare them with <. Commented Apr 27, 2015 at 21:52
  • how do i do that and then also sort the ones that get moved, by their order key? Commented Apr 27, 2015 at 21:52
  • DutGRIFF unfortunately, the arrays are coming from to separate databases entirely, so i cannot join. Commented Apr 27, 2015 at 21:53

2 Answers 2

3

This should be doable with uksort() and closures:

uksort( $posts, function ( $a, $b ) use ( $featured ) {
 $fa = ( isset( $featured[$a] ) ? $featured[$a]['order'] : INF );
 $fb = ( isset( $featured[$b] ) ? $featured[$b]['order'] : INF );
 if ( $fa != $fb ) return ( $fa < $fb ? -1 : +1 );
 // could add a tie-breaker comparison here
 return 0;
} );
answered Apr 27, 2015 at 21:59
3
  • That almost works, it returns the not-featured posts on top with the featured ones on the bottom but sorted correctly, like this: ab77 bk47 3aa2 13c5 4d55 Commented Apr 27, 2015 at 22:13
  • I'm trying to get to 13c5 4d55 ab77 bk47 3aa2 Commented Apr 27, 2015 at 22:14
  • Strange. Can you show the exact code you're using? And maybe use var_dump() instead of print_r() to display the arrays, so that there's no ambiguity about types? Commented Apr 28, 2015 at 0:24
0

This is the messy answer I came up with works.

$found, $not_found = array();
foreach ($posts as $key => $value) {
 if (array_key_exists($key, $featured)) {
 $found[$key] = $value;
 } else {
 $not_found[$key] = $value;
 }
}
usort($found, 'sort_by_order');
function sort_by_order ($a, $b) {
 return $a['order'] - $b['order'];
}
$new = array_merge($found, $not_found);
answered Apr 27, 2015 at 23:36

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.