Insert into ordered php array, move values - php

I have numbered array like
[0] => value 0
[1] => value 1
[2] => value 2
[3] => value 3
[4] => value 4
//keys 5-8 aren't set (I'm only demonstrating there could be a gap)
[9] => value 5
[10] => value 6
Is there any way to shuffle the array to move values when I add new to the specific position? So if i do something simillar to $array[1] = 'new value' it will change original value of 1 to new value of 2, 2 to 3 etc. up to 4 (then there is empty place in the example)?
Like this:
[0] => value 0
[1] => new value
[2] => value 1
[3] => value 2
[4] => value 3
[5] => value 4
[9] => value 5
[10] => value 6
Thank you very much for your help

Use array_splice .. Keep linear, not associated array, but places in array that need to be empty (for now) assign to null
Should work.

You could use the array_slice(). Check the examples below:
http://php.net/manual/en/function.array-splice.php

Related

Why this isn't working ? Php Array Auto Replace Values and short Array

Hi I need to select a rand value in the array removed and short the array i came out whit this small code but it keeps in an infinite loop but this is the weird look
<?php
$array=array("1","2","3","4","5","6","7","8","9","0");
$count=count($array);
for ($il=1;$il<=$count;$il++){
$array_value=array_rand($array, 1);
$array_value_key = array_search($array_value, $array);
$array_key_last=array_key_last($array);
for($if=0;$if<=$array_key_last;$if++){
if ($if==$array_value_key){
for($ia=$array_value_key;$ia<=$array_key_last;$ia++){
if ($ia<$array_key_last){
$ian=$ia+1;
$array[$ia]=$array[$ian];
}else{
unset($array[$ia]);
}
}
}
}
print_r($array);
}
?>
there the output can be different each time likes this but never ends
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
[5] => 7
[6] => 8
[7] => 9
[8] => 0
)
Array
(
[0] => 2
[1] => 3
[2] => 5
[3] => 6
[4] => 7
[5] => 8
[6] => 9
[7] => 0
)
^C
and i have to break it but as you can see in the first loop work as expected removes the number 4 and in the second loop removes the number 1 but don't finish the third loop
I have reviewed many times and get in to the conclusion of the problem it is on the line
$array[$ia]=$array[$ian];
if i add a echo here get printing a number it self to the infinity why?
$array[$ia]=$array[$ian];
echo $array[$ia],"\n";
The Problem is not in one line. It takes a few commands to interact:
array_rand returns the key of the element not the value
array_search returns (bool)false if it doesn't find the value (because of 1 this can happen)
You use $array_value_key to start a for loop. Because of 2 it can be (bool)false.
When you increment a boolean, it does not change. I.e. your $ia++ does nothing.
That's why $ia<=$array_key_last will never turn false and your loop runs forever.

Is this normal behaviour in php arrays? Array size get shortened when using numbered indexes out of order

So I'm learning Php, so as I was messing around with arrays to see how they work, I stumbled into this when I made two arrays.
$TestArray1 = array( 1 => 1, "string" => "string", 24, "other", 2 => 6, 8);
$TestArray2 = array( 6 => 1, "string" => "string", 24, "other", 1 => 6, 8);
But when I print them out with print_r() this is what I get (this also happens with var_dump by the way)
Array ( [1] => 1 [string] => string [2] => 6 [3] => other [4] => 8 )
Array ( [6] => 1 [string] => string [7] => 24 [8] => other [1] => 6 [9] => 8 )
As far as I can tell, by putting the two in the second array it overwrites the next possible spot with no key and then keeps going, shortening the array. So I thought that meant that if I use a 1 it would put it at the start but that does not happen either.
Is this normal or is there something wrong with my php installation?
Im using Ampps in windows 10 with php 7.3.
Thanks in advance
Good question.
What's happening is that when determining automatic numeric indexes, PHP will look to the largest numeric index added and increment it (or use 0 if there are none).
The key is optional. If it is not specified, PHP will use the increment of the largest previously used integer key.
What's happening with your first array is that as it is evaluated left-to-right, 24 is inserted at index 2 because the last numeric index was 1 => 1.
Then when it gets to 2 => 6, it overwrites the previous value at index 2. This is why 24 is missing from your first array.
If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten.
Here's a breakdown
$TestArray1 = [1 => 6]; // Array( [1] => 6 )
// no index, so use last numeric + 1
$TestArray1[] = 24; // Array( [1] => 6, [2] => 24 )
$TestArray1[2] = 6; // Array( [1] => 6, [2] => 6 )
When you manually add numeric indexes that are lower than previous ones (ie $TestArray2), they will be added as provided but their position will be later.
This is because PHP arrays are really maps that just pretend to be indexed arrays sometimes, depending on what's in them.
References are from the PHP manual page for Arrays

usort of session array not outputting as expected

I have a grid of img squares that can be dragged into any order using the sortable library. Each img is a visual representation of a result from a mySQL db query that selects any image that shares an 'imageparent' identifier. The order they're presented in the grid is taken from the 'imageorder' column in the database and starts at 0 and works in sequence up to the nth number of images returned.
The purpose of dragging the img grid is to be able to change the 'imageorder' index. On completion of the drag, the sortable library POSTS an 'imageorder' var by ajax to service.php and is received correctly. So rather than the original 0,1,2,3,4,5,6,7 order of the original, it sends a string like 2,1,0,3,4,5,7,6. Not too hard to grasp. After I switch the order the orderList var sent to service.php is always correct, but the array I end up sending to the db and setting as my session var becomes a little garbled in order after the second or third drag and I'm not quite sure why.
Code Examples and Comments
$_SESSION['selectedCsImages'] Array structure:
[0] => Array
(
[imagename] => "Title"
[imageorder] => 0
[imageid] => 43
)
[1] => Array
(
[imagename] => "Title"
[imageorder] => 1
[imageid] => 21
)
[2] => Array
(
[imagename] => "Title"
[imageorder] => 2
[imageid] => 3
)
etc...
Services.php extract:
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Turn the orderList posted into an array
$removeChars = array('"','[',']');
$orderList = str_replace($removeChars, "", $_POST['order']); // POST received fine.
$listArray = explode(",",$orderList);
// Retrieve the session array
$sorting = $_SESSION['selectedCsImages'];
/* My logic is that I compare the $sorting array to $listArray and reorder $sorting by 'imageorder' to match $listarray */
usort($sorting, function($a, $b) use ($listArray) {
return array_search($a['imageorder'], $listArray) - array_search($b['imageorder'], $listArray);
});
/* I now have a $sorting array that (sometimes, hence the problem) matches the order that the images had just been dragged into by the user. Typically, as I mentioned above, it's correct after the first drag, but not always after the second or third where it creates a new order that I can't see a pattern or logic in. */
/* Had there not been errors with the usort function, I (would) have a $sorting array in the order I want but with imageorder values referring to pre-sorting. I iterate through the array and set each key to 0, 1, 2, etc. so that I have an array in the correct order and with each imageorder correctly stating its place.*/
$i = 0;
foreach ($sorting as $key => $value) {
$sorting[$key]['imageorder'] = $i;
$i++;
}
/* The information is attempted to be sent to the db and, on success I update the session var */
// Database code (runs succesfully and updates the db as per the image orders found in the $sorting array)
$_SESSION['selectedCsImages'] = $sorting;
Debugging:
From debugging, it appears that something happens with the usort function when I call this page from ajax for the second or third time. Everything after this follows through fine and processes the correct or incorrect order as per expectations. The orderList var posted by sortable is correct each time. I'd provide a sample of the $sorted var after usort each time but it's as simple to describe it as the above array example in an order I didn't specify after dragging and I can't see a pattern in the seemingly random order it outputs.
From researching, I had thought that it was an issue with session vars being retained until the page is refreshed but it appears that the ajax call to services.php should refresh the $_SESSION['selectedCsImages'] var. I had also read that, perhaps, I was unknowingly using referenced array values and - as I source from a session var to a new array and, ultimately, save back to this session var from this array - I may have created some messy referencing feedback. However, I tried using $sorted = (array)clone(object)$_SESSION['selectedCsImages']; before attempting usort and the results didn't change.
PHP error logs are showing nothing.
Updates:
Per the suggestion of #Ayaou, I've checked the output of $listArray and am getting some unexpected results. I'd wrongly assumed that as the posted $orderList was correct, that the exploded array would not be a culprit.
Here's the output of print_r($listArray) after completing the following order swaps of 16 img elements: 1st with 2nd, 2nd last with last,6th with 7th:
1st and 2nd:
(
[0] => 1
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
[10] => 10
[11] => 11
[12] => 12
[13] => 13
[14] => 14
[15] => 15
)
last and 2nd last:
(
[0] => 1
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
[10] => 10
[11] => 11
[12] => 12
[13] => 13
[14] => 15
[15] => 14
)
6th with 7th:
(
[0] => 1
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 6
[6] => 5
[7] => 7
[8] => 8
[9] => 9
[10] => 10
[11] => 11
[12] => 12
[13] => 13
[14] => 15
[15] => 14
)
I was progressing with the idea that $listArray would show a sequential 0,1,2,3,etc. each time with only the two swapped items showing order changes. As it's not, I'll look back again at $orderList and check if my sortable library is updating the orders it's obtaining correctly from the updated session var. Older order swaps are being retained somewhere along the chain where they shouldn't.
The solution is on your sortable form (on the front end), so instead of sending the imageorder on your 'order' post data, send the imageid index.
Then change your sort callback like this
//Use imageid index instead of imageorder
usort($sorting, function($a, $b) use ($listArray) {
return array_search($a['imageid'], $listArray) - array_search($b['imageid'], $listArray);
});

How do I Spread out an array with possible empty slots?

I'm working with multi-dimesional arrays and am stumped trying to create a dynamic compatibility chart.
Given Data :
4 instances of Value 1
7 instances of Value 2
Ideal End Result Examples
If there are 4 value 1's and 7 value 2's
[0] Value 2
[1] Value 1
[2] Value 2
[3]
[4] Value 2
[5] Value 1
[6] Value 2
[7]
[8] Value 2
[9] Value 1
[10] Value 2
[11] Value 1
[12] Value 2
If there are 4 value 1's and 4 value 2's (try to evenly space them out without overlapping)
[0] Value 1
[1] Value 2
[2]
[3] Value 1
[4] Value 2
[5]
[6]
[7] Value 1
[8] Value 2
[9]
[10]
[11] Value 1
[12] Value 2
If there are 2 instances of 1 and three of 2.
[0] Value 1
[1] Value 2
[2]
[3]
[4]
[5]
[6] Value 2
[7]
[8]
[9]
[10]
[11] Value 1
[12] Value 2
I have bucket sizes of 12-24 for an array. In the example I use 12. If number of instances don't fit in 12 buckets, can move up all the way to 24. If it doesn't fit in 24, give an error.
Any loop that I've tried to make by using array_pop and reversing arrays creates empty holes in the middle of the array or it doesn't spread out the instances evenly.
Edit:
Here is what I've tried.
$table_array = range(0,12);
// Method 1
for ($i = 0; sizeof($table_array); $i++)
{
$ready_array[] = ($i % 2) ? array_pop($table_array) : array_shift($table_array);
}
// Method 2
for ($i = 0; $i < sizeof($table_array); $i++)
{
$index = ($i % 2) ? sizeof($table_array) - ceil($i / 2) : ceil($i / 2);
$ready_array[$index] = $table_array[$i];
}
ksort($ready_array);
Project Details and Goal
I have a list of compatible and incompatible pills.
I let the users select which pills and how many they're taking.
Based on that, I search the database and match up pills based on compatibility creating a lists known as Value 1 and Value 2.
I have a minimum 12 hour time frame to take the pills.
I'm supposed to space out lets say 4 of Calcium and 3 of Iron evenly across 12 hour period with 1 hour intervals and not let them overlap. If they choose 12 pills of Calcium and 12 pills of Iron, I can push up to 24 hours to make them take those pills.
Some ideas for your question :
Use array_chunk() and array_count_values()
<?php
$myarray = array(2,1,2,'',2,1,2,'',2,1,2,1,1,2,1,2,'',2,1,2,'',2,1,2,1,2);
$tests = array_chunk($myarray, 13);
//print_r($tests);
function mytest($tests)
{
foreach($tests as $test)
{
// play your test !
print_r(array_count_values($test));
}
}
// add your argument for your test
echo mytest($tests);
?>
output :
Array
(
[2] => 6
[1] => 5
[] => 2
)
Array
(
[2] => 7
[1] => 4
[] => 2
)
See for test : http://codepad.org/M9u5G0je

movement inside an multi-dimensional array

I have this array that I am displaying with a table how can i use user input for movement
currently 0 is assigned to every array but I plan on assigning other values to the array:
my question is - how can i move up, down, right, left, and move diagonally within the array using user input
Array ( [0] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[1] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[2] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[3] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[4] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[5] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[6] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
[7] => Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 0 [5] => 0 [6] => 0 [7] => 0 )
);
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
array(0,0,0,0,0,0,0,0),
It is for a checkers game no mysql.
I can already serialize the array into text file, but the text files needs to contain the start position and when each player makes a move put the location the piece move to in the text file then call back to the display
and I have already displayed the array into an html table
I am also trying to restrict movement to illegal square but that's a logic problem i need work on myself
will this loop work with code below
$row = 0;
print "<form>";
print "<table border = 1>";
while ($row < 8){ // Counts to 8. (from 0...7 = 8 times. 0 ... 8 = 9 times)
print "<tr>";
$row++;
$col = 0; // reset column to 0 each time printing one row.
while ($col < 8){
print "<td>";
if($board[$row][$col] == 0)
{
print "<input type=\"checkbox\" name=\"box[]\" value=\"$value\">";
// Add \ before " otherwise it will treat as the end of the quote.
}
print "</td>";
$col++;
}
print "</tr>";
}
print "</table>";
print "</form>";
I already created a database for keeping score but that will be finished after this
You need to define the available movement for the game, in this case, from the players point of view you can say that a player can move it's piece:
up-left
up-right
up-left-up-left
up-right-up-right
Note that the two last elements of the list are those of one piece eating another one. Once you know that you can take the current position of the piece and move it to the new one. I'm going to assume that for normal pieces you would use "N" and for queens "Q" although I will not use queens in my examples.
I will use a normal move and then an actual eating one:
//Piece at $board[$x][$y] moves diagonally to the left.
$board[$x-1][$y+1] = $board[$x][$y]; // This space is occupied
$board[$x][$y] = 0; //Now the space is empty
Now for the eating part. Lets imagine that the piece on $board[$x][$y] wants to eat the one that's in diagonally left.
//Eating action from $board[$x][$y]
$board[$x-1][$y+1] = 0; //It's been eaten!
$board[$x-2][$y+2] = $board[$x][$y]; // This space is occupied
So you could get an input from the user that included, the piece he wants to move, and what kind of movements he wants to do (I'm assuming, you will only allow the correct moves so I will not get into that). If you are reading it from a form submit for example you could get the movement, the position and the player (for orientation) as $_POST variables.
Then depending on those values modify the $board array. To do so, you could use conditionals or a switch, that's up to you.
$way = ($_POST['player'] === 'up')? 1:-1;
That last line will allow you to re-use the same code for the movements, multiplying the values you have to add to the current position to get to the new one, by the $way variable. For instance, going diagonally left would be:
//if player is 'up' then the value of $way is 1 so
$board[$x+(-1*$way)][$y+(1*$way)] = $board[$x][$y]; // position 2,2 becomes 1,3
//if player is not 'up' then the value of $way is -1 so
$board[$x+(-1*$way)][$y+(1*$way)] = $board[$x][$y]; // position 2,2 becomes 3,1
This should give you a starting point, all code was un-tested so I guess there may be some typos.
UPDATE
If all you want is to move from X,Y to X1Y1 then:
$board[$var3][$var4] = $board[$var1][$var2];
$board[$var1][$var2] = 0;
Is about all you need. :)
You can access every field of the board using its coordinates:
$array[$y][$x]
So, if you want to move something up, you can simply do:
$array[$y-1][$x] = $array[$y][$x];
$array[$y][$x] = 0;
I guess first you should fill with 1 and 2 the cells corresponding to each type of tile. Then you can assign numbers 3 and 4 to the ones that are coronated.
1.You can ask each player for example staring x,y and ending x,y
Then for doing a movment you first need to check it is allowed. Obviously starting $array[$x][$y] for player 1 should contain a 1. Then You need to make rules for this, For example if you are player 1 you can only go from $array[$x][$y] to $array[$x-1][$x-1], $array[$x-1][$y*1], etc when the place you wanna go is empty (filled with 0) Then you can check if more complicated moves are allowed like eating other player tile (which requires for example if you are player 1 to check things like $array[$x-2][$y-2] equals 0 and $array[$x-1][$y-1] equals 2. Then there is a series of more complicated verifications for the coronated ones that you should write. (besides always remember that you are moving within the limits of the array dimensions).
Finally you should alter the array cells that should be modified with the corresponding new values.

Categories