Move an array element to a new index in PHP
A lot of good answers. Here's a simple one built on the answer by @RubbelDeCatc. The beauty of it is that you only need to know the array key, not its current position (before repositioning).
/**
* Reposition an array element by its key.
*
* @param array $array The array being reordered.
* @param string|int $key They key of the element you want to reposition.
* @param int $order The position in the array you want to move the element to. (0 is first)
*
* @throws \Exception
*/
function repositionArrayElement(array &$array, $key, int $order): void
{
if(($a = array_search($key, array_keys($array))) === false){
throw new \Exception("The {$key} cannot be found in the given array.");
}
$p1 = array_splice($array, $a, 1);
$p2 = array_splice($array, 0, $order);
$array = array_merge($p2, $p1, $array);
}
Straight forward to use:
$fruits = [
'bananas'=>'12',
'apples'=>'23',
'tomatoes'=>'21',
'nuts'=>'22',
'foo'=>'a',
'bar'=>'b'
];
repositionArrayElement($fruits, "foo", 1);
var_export($fruits);
/** Returns
array (
'bananas' => '12',
'foo' => 'a', <-- Now moved to position #1
'apples' => '23',
'tomatoes' => '21',
'nuts' => '22',
'bar' => 'b',
)
**/
Works on numeric arrays also:
$colours = ["green", "blue", "red"];
repositionArrayElement($colours, 2, 0);
var_export($colours);
/** Returns
array (
0 => 'red', <-- Now moved to position #0
1 => 'green',
2 => 'blue',
)
*/
Demo
As commented, 2x array_splice
, there even is no need to renumber:
$array = [
0 => 'a',
1 => 'c',
2 => 'd',
3 => 'b',
4 => 'e',
];
function moveElement(&$array, $a, $b) {
$out = array_splice($array, $a, 1);
array_splice($array, $b, 0, $out);
}
moveElement($array, 3, 1);
Result:
[
0 => 'a',
1 => 'b',
2 => 'c',
3 => 'd',
4 => 'e',
];
Arrays in PHP are not actual array in the C sens but associative arrays. But the way to move a value from an index to another is quiet straight forward and is the same as in C++:
Copy the value to move to a temporary buffer, translate all the elements to crush the empty spot at the source position and in the same free up a spot on the destination position. Put the backup value in the destination spot.
function moveElement ($a , $i , $j)
{
$tmp = $a[$i];
if ($i > $j)
{
for ($k = $i; $k > $j; $k--) {
$a[$k] = $a[$k-1];
}
}
else
{
for ($k = $i; $k < $j; $k++) {
$a[$k] = $a[$k+1];
}
}
$a[$j] = $tmp;
return $a;
}
$a = array(0, 1, 2, 3, 4, 5);
print_r($a);
$a = moveElement($a, 1, 4);
echo ('1 -> 4');
print_r($a);
$a = moveElement($a, 5, 0);
echo ('5 -> 0' );
print_r($a);
Output:
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
)
1 -> 4Array
(
[0] => 0
[1] => 2
[2] => 3
[3] => 4
[4] => 1
[5] => 5
)
5 -> 0Array
(
[0] => 5
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 1
)
You'll need to add some Exception handling to have a complete code.
The solution from hakre with two array_splice commands doesn't work with named arrays. The key of the moved element will be lost.
Instead you can splice the array two times and merge the parts.
function moveElement(&$array, $a, $b) {
$p1 = array_splice($array, $a, 1);
$p2 = array_splice($array, 0, $b);
$array = array_merge($p2,$p1,$array);
}
How does it work:
- First: remove/splice the element from the array
- Second: splice the array into two parts at the position you want to insert the element
- Merge the three parts together
Example:
$fruits = array(
'bananas'=>'12',
'apples'=>'23',
'tomatoes'=>'21',
'nuts'=>'22',
'foo'=>'a',
'bar'=>'b'
);
moveElement($fruits, 1, 3);
// Result
['bananas'=>'12', 'tomatoes'=>'21', 'nuts'=>'22', 'apples'=>'23', 'foo'=>'a', 'bar'=>'b']