Question

Swap-up element in a multidimensional array with the sibling above it.

I want the element with the selected index in the array to swap it's position with the one above him.

  1. The element from it's position(N) to go to position(N-1)
  2. I want the element at position(N-1) to go at position(N),
  3. The resulting index should be reflecting correctly their new order in the array. array_values($tmparr); does sort the index correctly
  4. The Target Element to swap up can go to Position(0) but will never start at Position(0)
  5. The Element to swap down if at Position(0) Should go at position(1) not go at the End of the array.

Although this function explain semantically what i want to do it does not work at all.

function swaparray($tmparr,$posa,$posb){
 $vala = $tmparr[$posa];
 $valb = $tmparr[$posb];
 $tmparr[$posa] = $valb;
 $tmparr[$posb] = $vala;
 return $tmparr; }

The 2nd function shifts the intended target up but the above element is pushed up and goes to the end of the list if he is at position 0, it does not go under the target, so it doesnt work as intended it

 function swaparray($tmparr,$posa,$posb){
  $vala = $tmparr[$posa];
  $valb = $tmparr[$posb];
  unset($tmparr[$posa]);
  unset($tmparr[$posb]);
  $tmparr[$posa] = $valb;
  $tmparr[$posb] = $vala;
  $tmparr = array_values($tmparr);
 return $tmparr;
}

Reading further about my issue is seams Array_splice() could do the trick. What are your inputs about this?

Edit Answer: (PHP >= 4.3.8 )

The working solution with Array_splice()

 function swaparray($array, $n) {
     // taking out at $n
     $out = array_splice($array, $n, 1);
     // adding in at $n - 1
    array_splice($array, $n - 1, 0, $out);
    return $array;
 }

Here is the original multidimensional array

 Array ( [0] => Array ( [key1] => 1 [key2] => 1 [key3] => 1 [key4] => 1 )
         [1] => Array ( [key1] => 2 [key2] => 2 [key3] => 2 [key4] => 2 ) 
         [2] => Array ( [key1] => 3 [key2] => 3 [key3] => 3 [key4] => 3 ) 
         [3] => Array ( [key1] => 4 [key2] => 4 [key3] => 4 [key4] => 4 ) )

Here is an excerpt / exemple of want i wanted it to do.

[0] key1=1 key2=1 key3=1 key4=1
[1] key1=2 key2=2 key3=2 key4=2 
[2] key1=3 key2=3 key3=3 key4=3 <- 
[3] key1=4 key2=4 key3=4 key4=4

swaparray($tmparr,2);

[0] key1=1 key2=1 key3=1 key4=1
[1] key1=3 key2=3 key3=3 key4=3 <- 
[2] key1=2 key2=2 key3=2 key4=2 
[3] key1=4 key2=4 key3=4 key4=4     

swaparray($tmparr,1);

[0] key1=3 key2=3 key3=3 key4=3 <- 
[1] key1=1 key2=1 key3=1 key4=1
[2] key1=2 key2=2 key3=2 key4=2 
[3] key1=4 key2=4 key3=4 key4=4 

swaparray($tmparr,1);

[0] key1=1 key2=1 key3=1 key4=1 <-
[1] key1=3 key2=3 key3=3 key4=3  
[2] key1=2 key2=2 key3=2 key4=2 
[3] key1=4 key2=4 key3=4 key4=4 
Was it helpful?

Solution

The element from it's position(N) to go to position(N-1) I want the element at position(N-1) to go at position(N),

All you say is that you want to swap the two, where N is never 0 in a zero indexed array.

Move Element N to N-1:

/** 
  * [0] is top
  */
function moveUp(&$array, $n) {
    if ($n < 1)             throw new InvalidArgumentException();
    if (!isset($array[$n])) throw new InvalidArgumentException();
    // taking out at $n
    $out = array_splice($array, $n, 1);
    // adding in at $n - 1
    array_splice($array, $n - 1, 0, $out);
}

Usage:

$n = 2;
moveUp($array, $n);
var_dump($array);

Because the element at N-1 will get one element added in front, it will automatically move to N. Job done. array_splice is really powerful.

OTHER TIPS

This looks complex at first but its just basic variable swapping and retaining the key. What you need is to Reference with & in your function

$array = Array ( 
"0" => Array ( "key1" => 1 , "key2" => 1 , "key3" => 1 , "key4" => 1 ),
"1" => Array ( "key1" => 2 , "key2" => 2 , "key3" => 2 , "key4" => 2 ) ,
"2" => Array ( "key1" => 3 , "key2" => 3 , "key3" => 3 , "key4" => 3 ) ,
"3" => Array ( "key1" => 4 , "key2" => 4 , "key3" => 4 , "key4" => 4 ) );

swaparray($array,2,1);
var_dump($array);

Output

array
  0 => 
    array
      'key1' => int 1
      'key2' => int 1
      'key3' => int 1
      'key4' => int 1
  1 => 
    array
      'key1' => int 3
      'key2' => int 3
      'key3' => int 3
      'key4' => int 3
  2 => 
    array
      'key1' => int 2
      'key2' => int 2
      'key3' => int 2
      'key4' => int 2
  3 => 
    array
      'key1' => int 4
      'key2' => int 4
      'key3' => int 4
      'key4' => int 4

If you run it 3 times swaparray

swaparray($array,2,1);
swaparray($array,1,0);
swaparray($array,1,0);

var_dump($array);

YOu would get

array
  0 => 
    array
      'key1' => int 1
      'key2' => int 1
      'key3' => int 1
      'key4' => int 1
  1 => 
    array
      'key1' => int 3
      'key2' => int 3
      'key3' => int 3
      'key4' => int 3
  2 => 
    array
      'key1' => int 2
      'key2' => int 2
      'key3' => int 2
      'key4' => int 2
  3 => 
    array
      'key1' => int 4
      'key2' => int 4
      'key3' => int 4
      'key4' => int 4

Function Used

function swaparray(&$array, $originKey, $destinationKey) {
    $origin = isset($array[$originKey]) ? $array[$originKey] : false;
    $destination = isset($array[$destinationKey]) ? $array[$destinationKey] : false;

    if ($origin && $destination) {
        $array[$originKey] = $destination;
        $array[$destinationKey] = $origin;
        return true;
    }
    return false;
}

A quick simple version that should do pretty much what you want - just the same as all the other options on this page - I'm especially surprised that your own first function doesn't do what you need either? As far as I can see it should work perfectly... the only difference being is that it doesn't pass by reference.

function moveUp2(&$array, $n){
  if ( $n && array_key_exists($n, $array) ) {
    list( $array[$n-1], $array[$n] ) = array( $array[$n], $array[$n-1] );
  }
}

/// example usage
moveUp2( $array, 1 );

echo '<xmp>';
print_r($array);
echo '</xmp>';

Now obviously the above function assumes you are using numeric keys and that all keys in the array are in sequence - if for example you had keys proceeding like 0,1,3,4 -- then shifting 3 would mean that the value placed at 2 would appear at the end of the array...

If you find that array referencing is causing issues, just remove the & in the argument list and make sure the function returns $array. This would mean the example usage would change though, obviously:

/// example usage
$array = moveUp2( $array, 1 );

echo '<xmp>';
print_r($array);
echo '</xmp>';
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top