Move an array element to a new index in PHP

后端 未结 9 1846
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-03 04:47

I\'m looking for a simple function to move an array element to a new position in the array and resequence the indexes so that there are no gaps in the sequence. It doesnt ne

相关标签:
9条回答
  • 2020-12-03 04:51

    Take a look at this thread which describes a similar problem. The following solution is provided:

    /**
     * Move array element by index.  Only works with zero-based,
     * contiguously-indexed arrays
     *
     * @param array $array
     * @param integer $from Use NULL when you want to move the last element
     * @param integer $to   New index for moved element. Use NULL to push
     * 
     * @throws Exception
     * 
     * @return array Newly re-ordered array
     */
    function moveValueByIndex( array $array, $from=null, $to=null )
    {
      if ( null === $from )
      {
        $from = count( $array ) - 1;
      }
    
      if ( !isset( $array[$from] ) )
      {
        throw new Exception( "Offset $from does not exist" );
      }
    
      if ( array_keys( $array ) != range( 0, count( $array ) - 1 ) )
      {
        throw new Exception( "Invalid array keys" );
      }
    
      $value = $array[$from];
      unset( $array[$from] );
    
      if ( null === $to )
      {
        array_push( $array, $value );
      } else {
        $tail = array_splice( $array, $to );
        array_push( $array, $value );
        $array = array_merge( $array, $tail );
      }
    
      return $array;
    }
    
    0 讨论(0)
  • 2020-12-03 04:54

    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']
    
    0 讨论(0)
  • 2020-12-03 05:00

    May be I'm wrong but shouldn't it be easier just to make a copy of the array and then replace the values?

    function swap($input, $a, $b){
      $output = $input;
      $output[$a] = $input[$b];
      $output[$b] = $input[$a];
      return $output;
    }
    
    $array = ['a', 'c', 'b'];
    $array = swap($array, 1, 2);
    
    0 讨论(0)
  • 2020-12-03 05:03

    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',
    ];
    
    0 讨论(0)
  • 2020-12-03 05:03

    A function that preserves keys:

    function moveElementInArray($array, $toMove, $targetIndex) {
        if (is_int($toMove)) {
            $tmp = array_splice($array, $toMove, 1);
            array_splice($array, $targetIndex, 0, $tmp);
            $output = $array;
        }
        elseif (is_string($toMove)) {
            $indexToMove = array_search($toMove, array_keys($array));
            $itemToMove = $array[$toMove];
            array_splice($array, $indexToMove, 1);
            $i = 0;
            $output = Array();
            foreach($array as $key => $item) {
                if ($i == $targetIndex) {
                    $output[$toMove] = $itemToMove;
                }
                $output[$key] = $item;
                $i++;
            }
        }
        return $output;
    }
    
    $arr1 = Array('a', 'b', 'c', 'd', 'e');
    $arr2 = Array('A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e');
    
    print_r(moveElementInArray($arr1, 3, 1));
    print_r(moveElementInArray($arr2, 'D', 1));
    

    Ouput:

    Array
    (
        [0] => a
        [1] => d
        [2] => b
        [3] => c
        [4] => e
    )
    Array
    (
        [A] => a
        [D] => d
        [B] => b
        [C] => c
        [E] => e
    )
    
    0 讨论(0)
  • 2020-12-03 05:05

    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

    0 讨论(0)
提交回复
热议问题