Reputation: 36784
If I have an array like so (it could be any combination of numbers):
$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);
I want to move all the elements that equal 4 to the end of the array, while preserving the order of the other elements, so ideally my resulting array would be:
1, 2, 2, 3, 5, 2, 1, 4, 4
I thought I could acheve this by using a sort function:
uasort($arr, function($a, $b){
return $b == 4 ? -1 : 1;
});
Which moves the "4" elements to the end, but ruins the order of the other elements, this is my result with the above code:
2, 3, 1, 2, 5, 2, 1, 4, 4
How should my sorting handler function look? / Is there a better way to achieve this than sorting the array?
Note; I want to preserve my array keys (hence uasort
)
Upvotes: 3
Views: 1158
Reputation: 9000
Try with...
Example: https://eval.in/295552
CODE
<?php
// initial array
$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);
// key to move (as a new array for array_diff)
$key_removed = array(4);
// count the number of repetitions (for array_fill)
$key_repetitions = count(array_keys($arr, $key_removed[0], true));
// new temp_array without the removed key
$temp_arr1 = array_diff($arr, $key_removed);
// reorder array index
$temp_arr1 = array_values($temp_arr1);
// add to temp_array the removed key `key_repetitions` number of times
$temp_arr2 = array_fill(count($temp_arr1) + 1, $key_repetitions, $key_removed[0]);
// merge both
$arr = array_merge($temp_arr1, $temp_arr2);
var_dump($arr);
Upvotes: 0
Reputation: 74595
Here's one way to do it with uasort
:
$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);
uasort($arr, function($a, $b){
if ($a == 4) return -1;
if ($b == 4) return 1;
return 0;
});
$arr = array_reverse($arr, true);
print_r($arr);
The true
argument to array_reverse
preserves the keys in the array. The return 0
is optional but improves clarity in my opinion.
Output:
Array
(
[0] => 1
[3] => 2
[1] => 2
[4] => 3
[5] => 5
[7] => 2
[8] => 1
[2] => 4
[6] => 4
)
The fact that some of the keys corresponding to the same value are mixed up is unavoidable.
Upvotes: 3
Reputation: 897
How about this...??
<?php
$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);
$temp= array();
foreach($arr as $index => $value){
if($value == 4) {
array_push($temp, $value);
unset ($arr[$index]);
}
}
$result = array_merge($arr, $temp);
var_dump($result);
Gave me this:
array(9) {[0]=>int(1) [1]=>int(2) [2]=>int(2) [3]=>int(3) [4]=>int(5) [5]=>int(2) [6]=>int(1) [7]=>int(4) [8]=>int(4) }
Upvotes: 1
Reputation: 59681
This should work for you:
<?php
$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);
foreach($arr as $k => $v) {
if($v == 4) {
unset($arr[$k]);
$arr[$k] = $v;
}
}
print_r($arr);
?>
Output:
//before
Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 2 [4] => 3 [5] => 5 [6] => 4 [7] => 2 [8] => 1 )
//after ^ key ^ value ^ key ^ value
Array ( [0] => 1 [1] => 2 [3] => 2 [4] => 3 [5] => 5 [7] => 2 [8] => 1 [2] => 4 [6] => 4 )
//^ ^ ^ ^
Upvotes: 4