Подтвердить что ты не робот

Переместить элемент массива в новый индекс в PHP

Я ищу простую функцию, чтобы переместить элемент массива на новую позицию в массиве и повторно упорядочить индексы, чтобы в последовательности не было пробелов. Не нужно работать с ассоциативными массивами. У кого-нибудь есть идеи для этого?

$a = array(
      0 => 'a',
      1 => 'c',
      2 => 'd',
      3 => 'b',
      4 => 'e',
);
print_r(moveElement(3,1))
//should output 
    [ 0 => 'a',
      1 => 'b',
      2 => 'c',
      3 => 'd',
      4 => 'e' ]
4b9b3361

Ответ 1

Как прокомментировано, 2x array_splice, нет нужды даже перенумеровывать:

$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);

Результат:

[
    0 => 'a',
    1 => 'b',
    2 => 'c',
    3 => 'd',
    4 => 'e',
];

Ответ 2

Решение из hakre с двумя командами array_splice не работает с именованными массивами. Ключ перемещенного элемента будет потерян.

Вместо этого вы можете сращивать массив два раза и объединить части.

function moveElement(&$array, $a, $b) {
    $p1 = array_splice($array, $a, 1);
    $p2 = array_splice($array, 0, $b);
    $array = array_merge($p2,$p1,$array);
}

Как это работает:

  • Сначала: удалить/соединить элемент из массива
  • Во-вторых: сплайсируйте массив на две части в позиции, в которую вы хотите вставить элемент
  • Объедините три части вместе

Пример:

$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']

Ответ 3

Массивы в PHP не являются фактическим массивом в C-сенсе, а ассоциативными массивами. Но способ перемещения значения из индекса в другой является спокойным прямолинейным и тем же, что и в С++:

Скопируйте значение, чтобы переместиться во временный буфер, переведите все элементы, чтобы раздавить пустое место в исходной позиции и в том же самом свободном месте в месте назначения. Поместите резервное значение в место назначения.

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);

Вывод:

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
)

Вам нужно добавить некоторую обработку Исключения, чтобы иметь полный код.

Ответ 4

Я думаю, что вы ищете встроенную функцию usort. Пример со страницы ссылки:

<?php
function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}
?>

Ответ 5

Может быть, я ошибаюсь, но не проще ли просто сделать копию массива, а затем заменить значения?

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);

Ответ 6

Вам нужно создать вспомогательную переменную.

moveElement($a, $i,$j)
  {
  $k=$a[$i];
  $a[$i]=$a[$j];
  $a[$j]=$k;
  return $a;
  }

Ответ 7

Взгляните на этот поток, который описывает аналогичную проблему. Предусмотрено следующее решение:

/**
 * 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;
}

Ответ 8

Функция, которая сохраняет ключи:

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
)