将数组元素向左旋转(将第一个元素移动到最后并重新索引)

26

在PHP中,是否可以轻松地“旋转”数组?

就像这样: 1、2、3、4 -> 2、3、4、1

是否有某种内置的PHP函数可以实现这个功能?


请点击此处以查看如何向右旋转而非向左旋转。 - mickmackusa
15个回答

33
  $numbers = array(1,2,3,4);
  array_push($numbers, array_shift($numbers));
  print_r($numbers);

输出

Array
(
    [0] => 2
    [1] => 3
    [2] => 4
    [3] => 1
)

如果你只是像使用向量一样使用数组,并且索引值并不重要,那么这种方法是可以的。但是,如果你有一个关联数组想要旋转,这种方法会破坏你的数组键。请参考我的答案,它可以保留它们。 - Cam Jackson
@Cam,你说得完全正确,即使OP没有提到数组索引,只是值。你的答案对于那些正在寻找旋转数组元素两部分解决方案的人来说非常有价值。(给你点赞) - Wh1T3h4Ck5
是的,显然你的方法对楼主来说足够了,否则他不会接受它!但是,嗯,我觉得我可以加上我的答案,以防有人遇到和我一样的问题 :) - Cam Jackson
向右旋转:array_unshift($numbers,array_pop($numbers)); - Titus

28

大多数当前的答案是正确的,但仅适用于您不关心索引的情况:

$arr = array('foo' => 'bar', 'baz' => 'qux', 'wibble' => 'wobble');
array_push($arr, array_shift($arr));
print_r($arr);

输出:

Array
(
    [baz] => qux
    [wibble] => wobble
    [0] => bar
)
为保留你的索引,你可以像这样做:

To preserve your indices you can do something like:

$arr = array('foo' => 'bar', 'baz' => 'qux', 'wibble' => 'wobble');

$keys = array_keys($arr);
$val = $arr[$keys[0]];
unset($arr[$keys[0]]);
$arr[$keys[0]] = $val;

print_r($arr);

输出:

Array
(
    [baz] => qux
    [wibble] => wobble
    [foo] => bar
)

或许有人能比我更简洁地完成旋转,但这个方法仍然有效。


1
压缩代码:list($k,$v)=each($arr);unset($arr[$k]);$arr[$k]=$v;。你可能需要在前面加上 reset($arr); - Titus
当然,你需要容忍each()已被弃用。如果你在高尔夫比赛中,那么数组解构大括号比list()更短,而$arr将变成$a - mickmackusa

6

这非常简单,可以用多种方法来实现。例如:

$array   = array( 'a', 'b', 'c' );
$array[] = array_shift( $array );

4
循环数组并使用shiftpush可能是旋转数组的常见方式,但往往会破坏您的键。更加健壮的方法是使用array_mergearray_splice的组合。
/**
 * Rotates an array.
 * 
 * Numerical indexes will be renumbered automatically.
 * Associations will be kept for keys which are strings.
 * 
 * Rotations will always occur similar to shift and push,
 * where the number of items denoted by the distance are
 * removed from the start of the array and are appended.
 * 
 * Negative distances work in reverse, and are similar to
 * pop and unshift instead.
 * 
 * Distance magnitudes greater than the length of the array
 * can be interpreted as rotating an array more than a full
 * rotation. This will be reduced to calculate the remaining
 * rotation after all full rotations.
 * 
 * @param array $array The original array to rotate.
 * Passing a reference may cause the original array to be truncated.
 * @param int $distance The number of elements to move to the end.
 * Distance is automatically interpreted as an integer.
 * @return array The modified array.
 */
function array_rotate($array, $distance = 1) {
    settype($array, 'array');
    $distance %= count($array);
    return array_merge(
        array_splice($array, $distance), // Last elements  - moved to the start
        $array                          //  First elements - appended to the end
    );
}
// Example rotating an array 180°.
$rotated_180 = array_rotate($array, count($array) / 2);

另外,如果您也需要旋转密钥以匹配不同的值,您可以结合使用 array_keysarray_combinearray_rotatearray_values

/**
 * Rotates the keys of an array while keeping values in the same order.
 * 
 * @see array_rotate(); for function arguments and output.
 */
function array_rotate_key($array, $distance = 1) {
    $keys = array_keys((array)$array);
    return array_combine(
        array_rotate($keys, $distance), // Rotated keys
        array_values((array)$array)    //  Values
    );
}

或者,可以在保持键的顺序不变的同时旋转值(相当于调用匹配的array_rotate_key函数调用中的负距离)。

/**
 * Rotates the values of an array while keeping keys in the same order.
 * 
 * @see array_rotate(); for function arguments and output.
 */
function array_rotate_value($array, $distance = 1) {
    $values = array_values((array)$array);
    return array_combine(
        array_keys((array)$array),        // Keys
        array_rotate($values, $distance) //  Rotated values
    );
}

最后,如果您想要防止数字索引的重新编号。
/**
 * Rotates an array while keeping all key and value association.
 * 
 * @see array_rotate(); for function arguments and output.
 */
function array_rotate_assoc($array, $distance = 1) {
    $keys = array_keys((array)$array);
    $values = array_values((array)$array);
    return array_combine(
        array_rotate($keys, $distance),   // Rotated keys
        array_rotate($values, $distance) //  Rotated values
    );
}

进行一些基准测试可能会有益,但我认为每个请求只旋转少量数据,无论使用哪种方法,都不会明显影响性能。

也可以使用自定义排序函数来旋转数组,但这很可能过于复杂。例如usort


3

一种维护键和旋转的方法。使用与array_push(array,array_shift(array))相同的概念,而是使用2个array_slice的array_merge。

$x = array("a" => 1, "b" => 2, "c" => 3, 'd' => 4);

将第一个元素移动到末尾

array_merge(array_slice($x,1,NULL,true),array_slice($x,0,1,true)) //'b'=>2,'c'=>3,'d'=>4,'a'=>1

将最后一个元素移动到前面

array_merge(array_slice($x,count($x)-1,1,true) ,array_slice($x,0, //'d'=>4,'a'=>1,'b'=>2,'c'=>3


2
在Hackerrank上有一个关于数组旋转的任务: https://www.hackerrank.com/challenges/array-left-rotation/problem
提出的解决方案使用array_pusharray_shift将适用于除最后一个测试用例以外的所有测试用例,由于超时而失败。因此,array_pusharray_shift不会给您最快的解决方案。
以下是更快的方法:
function leftRotation(array $array, $n) {
   for ($i = 0; $i < $n; $i++) {
       $value = array[$i]; unset(array[$i]); array[] = $value;
   }
   return array;
}

2
您可以使用此函数:
    function arr_rotate(&$array,$rotate_count) {
        for ($i = 0; $i < $rotate_count; $i++) {
            array_push($array, array_shift($array));
        }
    }

用法:

    $xarr = array('1','2','3','4','5');
    arr_rotate($xarr, 2);
    print_r($xarr);

结果:

 Array ( [0] => 3 [1] => 4 [2] => 5 [3] => 1 [4] => 2 )

1
这是一个简洁的函数,但我认为可以稍作改进,以确保不会循环超过数组元素的数量。例如,arr_rotate($xarr, count($xarr)); 可以得到相同的结果顺序。添加 $rotate_count %= count($array); 这一行代码将确保最大迭代次数始终小于元素数量。 - Shaun Cockerill

1
$daynamesArray = array("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday");
array_push($daynamesArray, array_shift($daynamesArray)); //shift by one
array_push($daynamesArray, array_shift($daynamesArray)); //shift by two
print_r($daynamesArray);

输出从“Wednesday”开始:

Array ( [0] => Wednesday [1] => Thursday [2] => Friday [3] => Saturday [4] => Sunday [5] => Monday [6] => Tuesday 

1

是的,这里有一个我自己写的函数,其中$A是数组,$K是您想要旋转数组的次数:

function solution($A, $K) {

  for($i = 0; $i < $K; $i++): //we cycle $K
    $arrayTemp = $A;
    for($j = 0; $j < count($arrayTemp); $j++): // we cycle the array
       if($j == count($arrayTemp) - 1) $A[0] = $arrayTemp[$j]; // we check for the last position
       else $A[$j + 1] = $arrayTemp[$j]; // all but last position
    endfor;
  endfor;
 return $A;

}

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接