Personally, I would use a custom (anonymous) function in combination with usort() .
EDIT: Re is your comment. Hope this puts you on the right track. This function gives equal priority to elements that have an EN, or do not have an EN, or adjusted priority when only one has an EN.
usort($array,function ($a, $b) { $ac = strpos($a['countries'],'EN'); $bc = strpos($a['countries'],'EN'); if (($ac !== false && $bc !== false) || ($ac == false && $bc == false)) { return 0; } elseif ($ac !== false) { return 1; } else { return -1; } });
This function, on the other hand, gives equal priority if both have an EN, higher if there is an EN, and compares the text if neither of them has an EN.
usort($array,function ($a, $b) { $ac = strpos($a['countries'],'EN'); $bc = strpos($a['countries'],'EN'); if ($ac !== false && $bc !== false)) { return 0; } elseif ($ac !== false) { return 1; } elseif ($bc !== false) { return -1; } else { if ($a['countries'] == $b['countries']) { return 0; } elseif($a['countries'] > $b['countries']) { return 1; } else { return -1; } } });
Again, hopefully this will give you enough opportunity to move forward on your own. If you have any problems, feel free to leave more comments and I will try to help. Note, if you are linking several properties to weight: try a funky lock block, for example.
$ac = array_flip(explode(',',$a['countries'])); $bc = array_flip(explode(',',$b['countries'])); switch (true) { case array_key_exists('EN',$ac) && !array_key_exists('EN',$bc): return 1; case array_key_exists('DE',$ac) && !array_key_exists('EN',$bc) && !array_key_exists('EN',$bc): return 1;
Additional changes!
Actually, I was thinking more about the problem of complex sorting, and for your consideration I came up with the following solution. This will allow you to define numerical ratings based on the keywords that appear in the country index. Here is the code, including an example:
Array Example
$array = array( array( 'countries' => 'EN,DE,SP', ), array( 'countries' => 'EN,CH,SP', ), array( 'countries' => 'DE,SP,CH', ), array( 'countries' => 'DE,SV,SP', ), array( 'countries' => 'EN,SP,FR', ), array( 'countries' => 'DE,FR,CH', ), array( 'countries' => 'CH,EN,SP', ), );
The sort order
$rankings = array( 'EN' => 10, 'SP' => 8, 'FR' => 7, 'DE' => 5, 'CH' => 3, 'SV' => 1, ); usort($array, function (&$a, &$b) use ($rankings) { if (isset($a['_score'])) { $aScore = $a['_score']; } else { $aScore = 0; $aCountries = explode(',',$a['countries']); foreach ($aCountries as $country) { if (isset($rankings[$country])) { $aScore += $rankings[$country]; } } $a['_score'] = $aScore; } if (isset($b['_score'])) { $bScore = $b['_score']; } else { $bScore = 0; $bCountries = explode(',',$b['countries']); foreach ($bCountries as $country) { if (isset($rankings[$country])) { $bScore += $rankings[$country]; } } $b['_score'] = $bScore; } if ($aScore == $bScore) { return 0; } elseif ($aScore > $bScore) { return -1; } else { return 1; } });
Note. This code sorts the highest rating at the top of the array . If you want to change the behavior, change this:
elseif ($aScore > $bScore) {
to
elseif ($aScore < $bScore) {
Please note that more than was changed to a smaller character. Making this change will sort the lower ranking entries at the top of the array . Hope all this helps!
NOTE ALSO!
This code will make a small change to your array by adding the _score element to each array. I hope this is not a problem, since by preserving this value, I literally was able to increase the speed by more than two times (.00038 -.00041 to .00016 -.00018 in my tests). If not, remove the if blocks that retrieve the cached value, and let the contents of the else blocks be executed each time, except, of course, for the part in which the evaluation value is stored.
By the way, here is a dump of the var_export() array after sorting it:
array ( 0 => array ( 'countries' => 'EN,SP,FR', '_score' => 25, ), 1 => array ( 'countries' => 'EN,DE,SP', '_score' => 23, ), 2 => array ( 'countries' => 'EN,CH,SP', '_score' => 21, ), 3 => array ( 'countries' => 'CH,EN,SP', '_score' => 21, ), 4 => array ( 'countries' => 'DE,SP,CH', '_score' => 16, ), 5 => array ( 'countries' => 'DE,FR,CH', '_score' => 15, ), 6 => array ( 'countries' => 'DE,SV,SP', '_score' => 14, ), )
Enjoy it!