PHP sort array by subset
Simple O(n) solution.
$arr1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5);
$arr2 = array(36 => 1, 60 => 2, 12 => 1);
$result = array();
foreach($arr2 as $key => $value) {
$result[$key] = $arr1[$key];
unset($arr1[$key]);
}
foreach($arr1 as $key => $value) {
$result[$key] = $arr1[$key];
}
var_dump($result);
Output:
array(5) {
[36]=>
int(2)
[60]=>
int(4)
[12]=>
int(1)
[58]=>
int(3)
[72]=>
int(5)
}
use uksort
edit: fixed syntax/logic errors pointed out by malko. thank you.
$array_to_sort = array
(
12 => "blah",
36 => "foo",
58 => "blah",
60 => "blah",
72 => "blah",
90 => "bar"
);
$sorted_array = array(
36 => "foo data",
90 => "bar data",
12 => "blah data"
);
global $sorted_array_keys;
$sorted_array_keys = array_keys($sorted_array);
function cmp($a, $b)
{
global $sorted_array_keys;
$a_in_array = in_array($a, $sorted_array_keys);
$b_in_array = in_array($b, $sorted_array_keys);
if ($a_in_array && $b_in_array) {
return array_search($a, $sorted_array_keys) - array_search($b, $sorted_array_keys);
} else if ( $a_in_array ) {
return -1;
} else {
return 1;
}
}
uksort ( $array_to_sort , cmp );
print_r($array_to_sort);
This started off nice and clean, but ended up pretty ugly and unclear. I now I'm leaning toward some of the other answers rather than mine.
Here's an example using uksort with closure, it should be more effective on big array i think, but i haven't done any benchmark so... difficult to really confirm w/o test.
$a = array(
12 => 'blah'
,36 => 'foo'
,58 => 'blah'
,60 => 'blah'
,72 => 'blah'
,90 => 'bar'
);
$b = array(
36 => 'foo data'
,90 => 'bar data'
,12 => 'blah data'
);
$keysPosition = array_flip(array_keys($b));
uksort($a,function($a,$b) use ($keysPosition){
if(isset($keysPosition[$a],$keysPosition[$b])){
return $keysPosition[$a]>$keysPosition[$b]?1:-1;
}else if( isset($keysPosition[$a]) ){
return -1;
}else if( isset($keysPosition[$b]) ){
return 1;
}
return 0;
});
print_r($a);
result:
Array
(
[36] => foo
[90] => bar
[12] => blah
[72] => blah
[58] => blah
[60] => blah
)
If you can't use closure (php <5.3) you can do something similar using a global but it's not clean at all.