I cannot find an effective solution on rearranging/swapping an array item by its value by shifting by - 1
or + 1
. I'm making an order on tables, if the user wants to shift the order by moving the value upwards or downwards, the array should swap the value of the desired item upwards or downwards, for example:
If the user wants to move the item order upwards:
$desired_item_to_move = 'banana';
$default_order = array('orange', 'apple', 'banana', 'pineapple', 'strawberry');
// Typically it should return this:
array('orange', 'banana', 'apple', 'pineapple', 'strawberry');
As you can see that banana
and apple
has been swapped, due to banana
is moved upwards, if the user wants to move it down, it should swap pineapple
to banana
(from the first array) and so on.
I looked around on functions, array_replace
was closest, but it only replaces arrays.
Shifting up (assuming you've checked that the item is not already the first one):
$item = $array[ $index ];
$array[ $index ] = $array[ $index - 1 ];
$array[ $index - 1 ] = $item;
Shifting down:
$item = $array[ $index ];
$array[ $index ] = $array[ $index + 1 ];
$array[ $index + 1 ] = $item;
A useful function for the more general problem of moving an element of an array from one position to another:
function array_move(&$a, $oldpos, $newpos) {
if ($oldpos==$newpos) {return;}
array_splice($a,max($newpos,0),0,array_splice($a,max($oldpos,0),1));
}
This can then be used to solve the specific problem in the original question:
// shift up
array_move($array,$index,$index+1);
// shift down
array_move($array,$index,$index-1);
Note, there's no need to check whether or not you're already at the start/end of the array. Note also, this function does not preserve the array keys - moving elements while preserving keys is more fiddly.
$ret = array();
for ($i = 0; $i < count($array); $i++) {
if ($array[$i] == $desired_item_to_move && $i > 0) {
$tmp = array_pop($ret);
$ret[] = $array[$i];
$ret[] = $tmp;
} else {
$ret[] = $array[$i];
}
}
This will move up all instances of the desired element, putting the new array into $ret
.