I want to reverse the values in an indexed array using recursion. The output should be the same as array_reverse().
My code:
$array = [1,2,3,4,5,6,7];
function reverseString(&$s) {
if(count($s) < 2){
return;
}
$len = count($s);
$temp = $s[0];
$s[0] = $s[$len - 1];
$s[$len - 1] = $temp;
reverseString(array_slice($s, 1, $len - 2));
}
reverseString($array);
print_r($array);
returns:
Array (
[0] => 7
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 1 )
array_slice() is a link of an array part, am I right?
Why aren't the inner elements being affected by my recursive swapping technique?
A string and an array are two separate things. I cleared up your algorithm a bit:
<?php
$array = [1,2,3,4,5,6,7];
function reverseSequence(&$s) {
$len = count($s);
if($len < 2){
return;
}
$rest = array_slice($s, 1, $len - 2);
reverseSequence($rest);
$s = array_merge([$s[$len - 1]], $rest, [$s[0]]);
}
reverseSequence($array);
print_r($array);
The output obviously is:
Array
(
[0] => 7
[1] => 6
[2] => 5
[3] => 4
[4] => 3
[5] => 2
[6] => 1
)
If you have your error reporting switched on, you will see three of these Notices:
Notice: Only variables should be passed by reference...
This is because you are passing the output of array_slice() as the referenced parameter; to fix this you must declare `array_slice()'s output as a variable before passing it in.
The fact that you are seeing three Notices actually indicates that your recursive technique IS traverse as far as intended and doing the work, but the resultant element swapping is not being applied to the previous calls on $s -- IOW all of the subsequent recursive modifications are lost. (Demo)
#arkascha supplied the necessary fixes to your script about an hour before me, but I might write it slightly differently.
Code: (Demo)
function swapOutermost(&$a) {
$size = count($a);
if ($size > 1) {
$innerElements = array_slice($a, 1, -1);
swapOutermost($innerElements);
$a = array_merge(
[$a[$size - 1]], // last is put first
$innerElements, // recursed reference in the middle
[$a[0]] // first is put last
);
}
}
count() only once per recursive call -- arkascha fixed this
no return is written
-1 as the 3rd parameter of array_slice() has the same effect as your $len - 2.
Here is a recursive technique that only uses iterated count() calls -- no slicing or merging because it is passing the entire original input array each time. Only the targeted indexes change during recursion. I am swapping based on index incrementation using Symmetric Array Destructuring (a tool available from PHP7.1 and up).
Code: (Demo)
function swapOutermost(&$a, $i = 0) {
$last = count($a) - 1 - $i;
if ($i < $last) {
[$a[$i], $a[$last]] = [$a[$last], $a[$i]];
swapOutermost($a, ++$i);
}
}
swapOutermost($array);
...of course, since the count never changes, it would be more efficient to just pass it in once and reuse it.
function swapOutermost(&$a, $count, $i = 0) {
$last = $count - 1 - $i;
if ($i < $last) {
[$a[$i], $a[$last]] = [$a[$last], $a[$i]];
swapOutermost($a, $count, ++$i);
}
}
swapOutermost($array, count($array));
Now, your original snippet uses modification by reference, but you don't explicitly demand this in your question requirements -- only that recursion must be used. If you might entertain a recursive function that returns the variable instead (because, say, you want to be able to nest this call inside of another function), then here is one way that passes an ever shorter array with each level of recursion (as your original did):
Code: (Demo)
function recursiveArrayReverse($a) {
$size = count($a);
if ($size < 2) {
return $a;
}
return array_merge(
[$a[$size - 1]],
recursiveArrayReverse(
array_slice($a, 1, -1)
),
[$a[0]]
);
}
$array = [1, 2, 3, 4, 5, 6, 7];
$array = recursiveArrayReverse($array);
Related
I am trying to make a function where I get data from specific positions in an array, and then add(plus) the results together. Something like this:
$specificPositionsInArray = "1,4,12,27,40,42,48,49,52,53,56,58";
$dataArray = "1,2,3,4,5,6,7,8"; // More than hundred values.
myfunction($specificPositionsInArray) {
// Find position in array, based on $specificPositionsInArray and then
// plus the value with the previous value
// that is found in the $specificPositionsInArray.
// Something like:
$value = $value + $newValue;
return $value;
}
So if $specificPositionsInArray was 1,3,5
The $value that should be returned would be: 9 (1+3+5) (based on the $dataArray).
Maybe there is another way to do it, like without the function.
Here's a functional approach:
$specificPositionsInArray = array(1,3,7,6);
$dataArray = array(1,2,3,4,5,6,7,8);
function totalFromArrays($specificPositionsInArray, $dataArray) {
foreach ($specificPositionsInArray as $s){
$total += $dataArray[$s];
}
return $total;
}
$total = totalFromArrays($specificPositionsInArray, $dataArray);
echo $total;
You should look into arrays and how to handle them, you could have found the solution pretty easily. http://www.php.net/manual/en/book.array.php
//$specificPositionsInArray = array(1,4,12,27,40,42,48,49,52,53,56,58);
$specificPositionsInArray = array(1,3,5);
$dataArray = array(1,2,3,4,5,6,7,8);
$total=0;
foreach($specificPositionsInArray as $k => $v){
$total += $dataArray[$v-1];
}
echo $total;
The weird part about this is the $v-1 but because of how you want to handle the addition of the items, and an array starts with element 0, you have to subtract 1 to get to the right value.
So you want to do something like this:
$dataArray = array(1,2,3,4,5...); // 100+ values, not necessarily all integers or in ascending order
$specificPositions = array(1, 3, 5);
function addSpecificPositions($data, $positions) {
$sum = 0;
foreach($positions as $p)
$sum += $data[$p];
return $sum;
}
If you really want to keep your list of values in a string (like you have it in your example), you'll have to do an explode first to get them in array form.
Since it looks like your array is using numeric values for the keys this should be fairly easy to calculate. I refactored your code a little to make it easier to read:
$specificPositionsInArray = array(1,4,6,7);
By default PHP will assign numeric keys to each value in your array, so it will look like this to the interpreter.
array(
[0] => 1,
[1] => 4,
[2] => 6,
[3] => 7
)
This is the same for all arrays unless you specify a numeric or mixed key. Since the data array seems to just be values, too, and no keys are specified, you can simply target them with the key that they will be associated with. Say I use your array example:
$dataArray = array(1,2,3,4,5,6,7,8);
This will look like this to the parser:
array(
[0] => 1,
[1] => 2,
[2] => 3,
[3] => 4,
[4] => 5,
[5] => 6,
[6] => 7,
[7] => 8
)
If you wanted to select the number 6 from this array, you actually need to use $dataArray[5] since array keys start at zero. So for your function you would do this:
$specificPositionsInArray = array(1,4,6,7);
$dataArray = array(1,2,3,4,5,6,7,8);
calculate_array($specificPositionsInArray, $dataArray); // Returns 18
function calculate_array($keys, $data){
$final_value = 0; // Set final value to 0 to start
// Loop through values
foreach($keys as $key){
// Add the keys to our starting value
$final_value += $data[$key-1]; // minus 1 from key so that key position is human readable
}
// return the sum of the values
return $final_value;
}
I have the following code :
$json = json_decode(URL, true);
foreach($json as $var)
{
if($var[id] == $valdefined)
{
$number = $var[count];
}
}
With json it looks like this :
[{"id":"1","count":"77937"},
{"id":"2","count":"20"},
{"id":"4","count":"25"},
{"id":"5","count":"11365"}]
This is what the array ($json) looks like after jsondecode
Array ( [0] => Array ( [id] => 1 [count] => 77937 ) [1] => Array ( [id] => 2 [count] => 20 ) [2] => Array ( [id] => 4 [count] => 25 ) [3] => Array ( [id] => 5 [count] => 11365) )
is there a way to say what is $json[count] where $json[id] = 3 for example
I'm not sure about a better way, but this is also fine, provided the JSON object is not huge. php is pretty fast when looping through JSON. If the object is huge, then you may want to split it. What I personally do is make my JSON into an array of normal objects, sort them, and then searching is faster on sorted items.
EDIT
Do json_decode($your_thing, true); set it true to make it an associative array, and then the id would be key and and the count would be value. After you do this, getting the value with the ID should really be easy and far more efficient.
If you change the way you build your json object to look like this :-
{"1":77937,"2":20,"4":25,"5":11365}
And then use the json_decode() parameter 2 set to TRUE i.e. turn the json into an array.
Then you have a usable assoc array with the ID as the key like so:
<?php
$json = '{"1":77937,"2":20,"4":25,"5":11365}';
$json_array = json_decode($json, TRUE);
print_r( $json_array);
?>
Resulting in this array
Array
(
[1] => 77937
[2] => 20
[4] => 25
[5] => 11365
)
Which you can do a simple
$number = json_array( $valdefined );
Or better still
if ( array_key_exists( $valdefined, $json_array ) ) {
$number = json_array( $valdefined );
} else {
$number = NULL; // or whatever value indicates its NON-EXISTANCE
}
Short answer to your initial question: why can't you write $json['count'] where $json['id'] = 3? Simply because PHP isn't a query language. The way you formulated the question reads like a simple SQL select query. SQL will traverse its indexes, and (if needs must) will perform a full table scan, too, its Structured Query Language merely enables you not to bother writing out the loops the DB will perform.
It's not that, because you don't write a loop, there is no loop (the absence of evidence is not the evidence of absence). I'm not going to go all Turing on you, but there's only so many things we can do on a machine level. On the lower levels, you just have to take it one step at a time. Often, this means incrementing, checking and incrementing again... AKA recursing and traversing.
PHP will think it understands what you mean by $json['id'], and it'll think you mean for it to return the value that is referenced by id, in the array $json, whereas you actually want $json[n]['id'] to be fetched. To determine n, you'll have to write a loop of sorts. Some have suggested sorting the array. That, too, like any other array_* function that maps/filters/merges means looping over the entire array. There is just no way around that. Since there is no out-of-the-box core function that does exactly what you need to do, you're going to have to write the loop yourself.
If performance is important to you, you can write a more efficient loop. Below, you can find a slightly less brute loop, a semi Interpolation search. You could use ternary search here, too, implementing that is something you can work on.
for ($i = 1, $j = count($bar), $h = round($j/2);$i<$j;$i+= $h)
{
if ($bar[++$i]->id === $search || $bar[--$i]->id === $search || $bar[--$i]->id === $search)
{//thans to short-circuit evaluation, we can check 3 offsets in one go
$found = $bar[$i];
break;
}//++$i, --$i, --$i ==> $i === $i -1, increment again:
if ($bar[++$i]->id > $search)
{// too far
$i -= $h;//return to previous offset, step will be halved
}
else
{//not far enough
$h = $j - $i;//set step the remaining length, will be halved
}
$h = round($h/2);//halve step, and round, in case $h%2 === 1
//optional:
if(($i + $h + 1) === $j)
{//avoid overflow
$h -= 1;
}
}
Where $bar is your json-decoded array.
How this works exactly is explained below, as are the downsides of this approach, but for now, more relevant to your question: how to implement:
function lookup(array $arr, $p, $val)
{
$j = count($arr);
if ($arr[$j-1]->{$p} < $val)
{//highest id is still less value is still less than $val:
return (object) array($p => $val, 'count' => 0, 'error' => 'out of bounds');
}
if ($arr[$j-1]->{$p} === $val)
{//the last element is the one we're looking for?
return $end;
}
if ($arr[0]->{$p} > $val)
{//the lowest value is still higher than the requested value?
return (object) array($p => $val, 'count' => 0, 'error' => 'underflow');
}
for ($i = 1, $h = round($j/2);$i<$j;$i+= $h)
{
if ($arr[++$i]->{$p} === $val || $arr[--$i]->{$p} === $val || $arr[--$i]->{$p} === $val)
{//checks offsets 2, 1, 0 respectively on first iteration
return $arr[$i];
}
if ($arr[$i++]->{$p} < $val && $arr[$i]->{$p} > $val)
{//requested value is in between? don't bother, it won't exist, then
return (object)array($p => $val, 'count' => 0, 'error' => 'does not exist');
}
if ($arr[++$i]->{$p} > $val)
{
$i -= $h;
}
else
{
$h = ($j - $i);
}
$h = round($h/2);
}
}
$count = lookup($json, 'id', 3);
echo $count['count'];
//or if you have the latest version of php
$count = (lookup($json, 'id', 3))['count'];//you'll have to return default value for this one
Personally, I wouldn't return a default-object if the property-value pair wasn't found, I'd either return null or throw a RuntimeException, but that's for you to decide.
The loop basically works like this:
On each iteration, the objects at offset $i, $i+1 and $i-1 are checked.
If the object is found, a reference to it is assigned to $found and the loop ends
The object isn't found. Do either one of these two steps:
ID at offset is greater than the one we're looking for, subtract step ($h) from offset $i, and halve the step. Loop again
ID is smaller than search (we're not there yet): change step to half of the remaining length of the array
A diagram will show why this is a more "clever" way of looping:
|==========x=============================|//suppose x is what we need, offset 11 of a total length 40:
//iteration 1:
012 //checked offsets, not found
|==========x=============================|
//offset + 40/2 == 21
//iteration 2:
012//offsets 20, 21 and 22, not found, too far
|==========x=============================|
//offset - 21 + round(21/2)~>11 === 12
//iteration 3:
123 //checks offsets 11, 12, 13) ==> FOUND
|==========x=============================|
assign offset-1
break;
Instead of 11 iterations, we've managed to find the object we needed after a mere 3 iterations! Though this loop is somewhat more expensive (there's more computation involved), the downsides rarely outweigh the benefits.
This loop, as it stands, though, has a few blind-spots, so in rare cases it will be slower, but on average it performs pretty well. I've tested this loop a couple of times, with an array containing 100,000 objects, looking for id random(1,99999) and I haven't seen it take more time than .08ms, on average, it manages .0018ms, which is not bad at all.
Of course, you can improve on the loop by using the difference between the id at the offset, and the searched id, or break if id at offset $i is greater than the search value and the id at offset $i-1 is less than the search-value to avoid infinite loops. On the whole, though, this is the most scalable and performant loopup algorithm provided here so far.
Check the basic codepad in action here
Codepad with loop wrapped in a function
Is there a native function that works like combine_subarrays below?
$foo = array(
array(1,2,3),
array(4,5,6),
array(7,8,9)
);
$n = 1; // desired element's position in each subarray
$bar = combine_subarrays($foo, $n);
// Result: $bar is array of all elements in 1st positions - [2,5,8]
Right now, I foreach through $foo and push the $nth element onto a new array that is then returned. If there's a native way to do it, it would be better.
A quick solution with global reference to $n would be:
$n = 1;
$bar = array_map(function($item) {
global $n;
return $item[$n];
},
$foo);
And the result is:
Array ( [0] => 2 [1] => 5 [2] => 8 )
There is no function that does exactly that but several ways to use the array functions instead of writing a loop. For example array_reduce*:
$bar = array_reduce($foo, function(&$result, $item) use ($n) {
$result[] = $item[$n]
});
**array_map is probably the better choice, it also preserves the original keys. See answer by #zeldi*
I am really new in PHP and need a suggestion about array search.
If I want to search for an element inside a multidimensional array, I can either use array_filter or I can loop through the array and see if an element matching my criteria is present.
I see both suggestion at many places. Which is faster? Below is a sample array.
Array (
[0] => Array (
[id] => 4e288306a74848.46724799
[question] => Which city is capital of New York?
[answers] => Array (
[0] => Array (
[id] => 4e288b637072c6.27436568
[answer] => New York
[question_id_fk] => 4e288306a74848.46724799
[correct] => 0
)
[1] => Array (
[id] => 4e288b63709a24.35955656
[answer] => Albany
[question_id_fk] => 4e288306a74848.46724799
[correct] => 1
)
)
)
)
I am searching like this.
$thisQuestion = array_filter($pollQuestions, function($q) {
return questionId == $q["id"];
});
I know, the question is old, but I disagree with the accepted answer. I was also wondering, if there was a difference between a foreach() loop and the array_filter() function and found the following post:
http://www.levijackson.net/are-array_-functions-faster-than-loops/
Levi Jackson did a nice job and compared the speed of several loop and array_*() functions. According to him a foreach() loop is faster than the array_filter() function. Although it mostly doesn't make such a big difference, it starts to matter, when you have to process a lot of data.
I've made a test script because I was a little skeptical ...how can an internal function be slower than a loop...
But actually it's true. Another interesting result is that php 7.4 is almost 10x faster than 7.2!
You can try yourself
<?php
/*** Results on my machine ***
php 7.2
array_filter: 2.5147440433502
foreach: 0.13733291625977
for i: 0.24090600013733
php 7.4
array_filter: 0.057109117507935
foreach: 0.021071910858154
for i: 0.027867078781128
**/
ini_set('memory_limit', '500M');
$data = range(0, 1000000);
// ARRAY FILTER
$start = microtime(true);
$newData = array_filter($data, function ($item) {
return $item % 2;
});
$end = microtime(true);
echo "array_filter: ";
echo $end - $start . PHP_EOL;
// FOREACH
$start = microtime(true);
$newData = array();
foreach ($data as $item) {
if ($item % 2) {
$newData[] = $item;
}
}
$end = microtime(true);
echo "foreach: ";
echo $end - $start . PHP_EOL;
// FOR
$start = microtime(true);
$newData = array();
$numItems = count($data);
for ($i = 0; $i < $numItems; $i++) {
if ($data[$i] % 2) {
$newData[] = $data[$i];
}
}
$end = microtime(true);
echo "for i: ";
echo $end - $start . PHP_EOL;
I know it's an old question, but I'll give my two cents: for me, using a foreach loop was much faster than using array_filter. Using foreach, it took 1.4 seconds to perform a search by id, and using the filter it took 8.6 seconds.
From my own experience, foreach is faster. I think it has something to do with function call overhead, arguments check, copy to variable return instruction, etc.. When using a basic syntax, the parsed code is more likely to be closer to the compiled/interpreted bytecodes, have better optimization down the core.
The common rule is : anything is simplier, run faster (imply less check, less functionnality, as long as it has all you need)
Array_Filter
Iterates over each value in the input array passing them to the
callback function. If the callback function returns true, the current
value from input is returned into the result array. Array keys are
preserved.
as for me same.
Is it possible to easily 'rotate' an array in PHP?
Like this:
1, 2, 3, 4 -> 2, 3 ,4 ,1
Is there some kind of built-in PHP function for this?
$numbers = array(1,2,3,4);
array_push($numbers, array_shift($numbers));
print_r($numbers);
Output
Array
(
[0] => 2
[1] => 3
[2] => 4
[3] => 1
)
Most of the current answers are correct, but only if you don't care about your indices:
$arr = array('foo' => 'bar', 'baz' => 'qux', 'wibble' => 'wobble');
array_push($arr, array_shift($arr));
print_r($arr);
Output:
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);
Output:
Array
(
[baz] => qux
[wibble] => wobble
[foo] => bar
)
Perhaps someone can do the rotation more succinctly than my four-line method, but this works anyway.
It's very simple and could be done in many ways. Example:
$array = array( 'a', 'b', 'c' );
$array[] = array_shift( $array );
Looping through the array, and shift-ing and push-ing, may be a common way to rotate an array, however it can often mess up your keys. A more robust method is using a combination of array_merge and array_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);
Alternatively, if you also find the need to rotate keys so that they match with different values, you can combine array_keys, array_combine, array_rotate, and array_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
);
}
Or alternatively rotating the values while keeping the keys in the same order (equivalent to calling the negative distance on the matching array_rotate_key function call).
/**
* 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
);
}
And finally, if you want to prevent renumbering of numerical indexes.
/**
* 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
);
}
It could be beneficial to perform some benchmark tests, however, I expect that a small handful of rotations per request wouldn't affect performance noticeably regardless of which method is used.
It should also be possible to rotate an array by using a custom sorting function, but it would most likely be overly complicated. i.e. usort.
A method to maintain keys and rotate. using the same concept as array_push(array, array_shift(array)), instead we will use array_merge of 2 array_slices
$x = array("a" => 1, "b" => 2, "c" => 3, 'd' => 4);
To move the First element to the end
array_merge(array_slice($x, 1, NULL, true), array_slice($x, 0, 1, true)
//'b'=>2, 'c'=>3, 'd'=>4, 'a'=>1
To move the last element to the front
array_merge(array_slice($x, count($x) -1, 1, true), array_slice($x, 0,
//'d'=>4, 'a'=>1, 'b'=>2, 'c'=>3
you can use this function:
function arr_rotate(&$array,$rotate_count) {
for ($i = 0; $i < $rotate_count; $i++) {
array_push($array, array_shift($array));
}
}
usage:
$xarr = array('1','2','3','4','5');
arr_rotate($xarr, 2);
print_r($xarr);
result:
Array ( [0] => 3 [1] => 4 [2] => 5 [3] => 1 [4] => 2 )
There's a task about array rotation on Hackerrank: https://www.hackerrank.com/challenges/array-left-rotation/problem.
And proposed solution with array_push and array_shift will work for all test cases except the last one, which fails due to timeout. So, array_push and array_shift will give you not the fastest solution.
Here's the faster approach:
function leftRotation(array $array, $n) {
for ($i = 0; $i < $n; $i++) {
$value = array[$i]; unset(array[$i]); array[] = $value;
}
return array;
}
Use array_shift and array_push.
$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);
The output starts at "Wednesday":
Array ( [0] => Wednesday [1] => Thursday [2] => Friday [3] => Saturday [4] => Sunday [5] => Monday [6] => Tuesday
Yes it is, here is a function I did myself, where $A is the array and $K the number of times you want to rotate the array:
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;
}
The logic is to swap the elements. Algorithm may look like -
for i = 0 to arrayLength - 1
swap( array[i], array[i+1] ) // Now array[i] has array[i+1] value and
// array[i+1] has array[i] value.
No. Check the documentation for array_shift and its related functions for some tools you can use to write one. There might even be an array_rotate function implemented in the comments of that page.
It's also worth reading through the array functions listed on the left-hand sidebar to get a full understanding of what array functions are available in PHP.
Here's a function to rotate an array (zero-indexed array) to any position you want:
function rotateArray($inputArray, $rotateIndex) {
if(isset($inputArray[$rotateIndex])) {
$startSlice = array_slice($inputArray, 0, $rotateIndex);
$endSlice = array_slice($inputArray, $rotateIndex);
return array_merge($endSlice, $startSlice);
}
return $inputArray;
}
$testArray = [1,2,3,4,5,6];
$testRotates = [3, 5, 0, 101, -5];
foreach($testRotates as $rotateIndex) {
print_r(rotateArray($testArray, $rotateIndex));
}
Not too dissimilar to the first snippet in ShaunCockerill's answer, I also endorse not making iterated functions calls to perform the rotation. In fact, I'll recommend using early returns to optimize performance and reduce the total number of function calls needed.
The following snippet is the "move left" version of the "move right" version that I posted here. In my demo, there is a single, static input array and the foreach() loop merely changes the desired amount of rotation (0 to 9).
Code: (Demo)
function shiftPop(array $indexedArray, int $shiftPopsCount): array
{
$count = count($indexedArray);
if ($count < 2) {
return $indexedArray;
}
$remainder = $shiftPopsCount % $count;
if (!$remainder) {
return $indexedArray;
}
return array_merge(
array_splice($indexedArray, $remainder),
$indexedArray
);
}
$array = [1, 2, 3, 4];
foreach (range(0, 9) as $moves) {
var_export(shiftPop($array, $moves));
echo "\n---\n";
}
The first if block in my snippet is not engaged by my demo because my array always has 4 elements. The second if block is engaged, when $moves is 0, 4, and 8 -- in these cases, the input is identical to the desired output, so calling array_merge() and array_splice() is pointless.