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.
I have a column pack_size in a table called product_master_test. The problem that I am facing is that the pack_size is in mixed formats, there is no uniformity to it.
For example:
4 x 2kg (pack size should be 4)
48-43GM (pack size should be 48)
12 x 1BTL (pack size should be 12)
1 x 24EA (pack size should be 24)
I've been thinking about different approaches, but I can't think of anything that would work without having a lot of IF statements in the query/PHP code. Is there a solution that I am missing?
I do have the file in Excel, if there is an easier way to process it using PHP.
I am not including any code, as I'm not entirely sure where to start with this problem.
Using a regex to split the pack size could at least give you the various components which you can then (possibly) infer more from...
$packs = ["4 x 2kg","48-43GM","12 x 1BTL","1 x 24EA", "12 X 1 EA"];
foreach ( $packs as $size ) {
if ( preg_match("/(\d*)(?:\s+)?[xX-](?:\s+)?(\d+)(?:\s+)?(\w*)/", $size, $match) == 1 ) {
print_r($match);
}
else {
echo "cannot determine - ".$size.PHP_EOL;
}
}
(regex can probably be optimised, not my area of expertise). It basically splits it to be a number, some space with either a x or a - and then another number followed by the units (some text). The above with the test cases gives...
Array
(
[0] => 4 x 2kg
[1] => 4
[2] => 2
[3] => kg
)
Array
(
[0] => 48-43GM
[1] => 48
[2] => 43
[3] => GM
)
Array
(
[0] => 12 x 1BTL
[1] => 12
[2] => 1
[3] => BTL
)
Array
(
[0] => 1 x 24EA
[1] => 1
[2] => 24
[3] => EA
)
Array
(
[0] => 12 X 1 EA
[1] => 12
[2] => 1
[3] => EA
)
With the else part it should also give you the ones it cannot determine and perhaps allow you to change it accordingly.
You could present an associative array of all the strings from the table as keys corresponding with correct pack_size you desire.
$packsize = ["4 x 2kg" => 4, "48-43GM" => 48, "12 x 1BTL" => 12, "1 x 24EA" => 24]; //add all pack_sizes here
echo $packsize["4 x 2kg"]; // Output: 4
Now you could get the acutal pack size via the key of associative array. It could save some time you would spend making if/else conditions or switching the input. I'm not sure if there is something wrong with this approach, so correct me if so.
I am trying to calculate the winning order of golfers when they are tied in a competition.
These golf competitions are using the "stableford" points scoring system, where you score points per hole with the highest points winning. Compared to normal golf "stroke play" where the lowest score wins (though this also has the countback system, only calculating the lowest score in the event of a tie...)
The rules are to use a "countback". i.e., if scores are tied after 9 holes, the best placed of the ties is the best score from the last 8 holes. then 7 holes, etc.
The best I can come up with is 2 arrays.
An array with all the players who tied in a given round. ($ties)
One which has the full score data in (referencing the database playerid) for all 9 holes. ($tie_perhole)
I loop through array 1, pulling data from array 2 and using the following formula to create a temporary array with the highest score:
$max = array_keys($array,max($array));
If $max only has 1 item, this player is the highest scorer. the loop through the first array is "by reference", so on the next iteration of the loop, his playerid is now longer in the array, thus ignored. this continues until there is only 1 playerid left in the first array.
However, it only works if a single player wins in each iteration. The scenario that doesn't work is if a sub-set of players tie on any iterations / countbacks.
I think my problem is the current structure I have will need the original $ties array to become split, and then to continue to iterate through the split arrays in the same way...
As an example...
The $ties array is as follows:
Array
(
[18] => Array
(
[0] => 77
[1] => 79
[2] => 76
[3] => 78
)
)
The $tie_perhole (score data) array is as follows:
Array
(
[18] => Array
(
[77] => Array
(
[9] => 18
[8] => 16
[7] => 14
[6] => 12
[5] => 10
[4] => 8
[3] => 6
[2] => 4
[1] => 2
)
[79] => Array
(
[9] => 18
[8] => 17
[7] => 15
[6] => 14
[5] => 11
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
[76] => Array
(
[9] => 18
[8] => 16
[7] => 14
[6] => 12
[5] => 10
[4] => 8
[3] => 6
[2] => 4
[1] => 2
)
[78] => Array
(
[9] => 18
[8] => 17
[7] => 15
[6] => 13
[5] => 11
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
)
)
So in this competition, player's 78 and 79 score highest on the 8th hole countback (17pts), so 1st and 2nd should be between them. Player 79 should then be 1st on the 6th hole countback (14pts, compared to 13pts). The same should occur for 3rd and 4th place with the 2 remaining other players.
There are other scenarios that can occur here, in that within a competition, there will likely be many groups of players (of different amounts) on different tied points through the leaderboard.
Also note, there will be some players on the leaderboard who are NOT tied and stay in their current outright position.
The basics of the working code I have is:
foreach ($ties as $comparekey => &$compareval) {
$tie_loop = 0;
for ($m = 9; $m >= 1; $m--) {
$compare = array();
foreach ($compareval as $tie) {
$compare[$tie] = $tie_perhole[$comparekey][$tie][$m];
}
$row = array_keys($compare,max($compare));
if (count($row) == 1) {
$indexties = array_search($row[0], $ties[$comparekey]);
unset($ties[$comparekey][$indexties]);
// Now update this "winners" finishing position in a sorted array
// This is a multidimensional array too, with custom function...
$indexresults = searchForId($row[0], $comp_results_arr);
$comp_results_arr[$indexresults][position] = $tie_loop;
$tie_loop++;
}
// I think I need conditions here to filter if a subset of players tie
// Other than count($row) == 1
// And possibly splitting out into multiple $ties arrays for each thread...
if (empty($ties[$comparekey])) {
break;
}
}
}
usort($comp_results_arr, 'compare_posn_asc');
foreach($comp_results_arr as $row) {
//echo an HTML table...
}
Thanks in advance for any helpful insights, tips, thoughts, etc...
Robert Cathay asked for more scenarios. So here is another...
The leaderboard actually has more entrants (player 26 had a bad round...), but the code i need help with is only bothered about the ties within the leaderboard.
Summary leaderboard:
Points Player
21 48
21 75
20 73
20 1
13 26
This example produces a $tie_perhole array of:
Array
(
[21] => Array
(
[75] => Array
(
[9] => 21
[8] => 19
[7] => 16
[6] => 14
[5] => 12
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
[48] => Array
(
[9] => 21
[8] => 19
[7] => 16
[6] => 13
[5] => 11
[4] => 9
[3] => 8
[2] => 5
[1] => 3
)
)
[20] => Array
(
[73] => Array
(
[9] => 20
[8] => 18
[7] => 16
[6] => 13
[5] => 11
[4] => 8
[3] => 6
[2] => 5
[1] => 3
)
[1] => Array
(
[9] => 20
[8] => 17
[7] => 16
[6] => 14
[5] => 12
[4] => 9
[3] => 7
[2] => 4
[1] => 2
)
)
)
In this example, the array shows that players 75 and 48 scored 21 points that player 75 will eventually win on the 6th hole countback (14pts compared to 13pts) and player 48 is 2nd. In the next tied group, players 73 and 1 scored 20 points, and player 73 will win this group on the 8th hole countback and finishes 3rd (18 pts compared to 17 pts), with player 1 in 4th. player 26 is then 5th.
Note, the $tie_loop is added to another array to calculate the 1st to 5th place finishing positions, so that is working.
Hopefully that is enough to help.
Ok, so I don't understand golf at all... hahaha BUT! I think I got the gist of this problem, so heres my solution.
<?php
/**
* Author : Carlos Alaniz
* Email : Carlos.glvn1993#gmail.com
* Porpuse : Stackoverflow example
* Date : Aug/04/2015
**/
$golfers = [
"A" => [1,5,9,1,1,2,3,4,9],
"B" => [2,6,4,2,4,4,1,9,3],
"C" => [3,4,9,8,1,1,5,1,3],
"D" => [1,5,1,1,1,5,4,5,8]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
$positions = array(); // The score numer is the key!
foreach ($golfers as $golfer=>$score ) { // Get key and value
$score_sub = array_slice($score,0,$hole); // Get the scores subset, first iteration is always all holes
$total_score = (string)array_sum($score_sub); // Get the key
if(!isset($positions[$total_score])){
$positions[$total_score] = array(); // Make array
}
$positions[$total_score][] = $golfer; // Add Golpher to score.
}
ksort($positions, SORT_NUMERIC); // Sort based on key, low -> high
return array(end($positions), key($positions)); // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
if ($hole == 0) return;
$winner = get_winners($golfers,$hole); // Get all ties, if any.
if(count($winner[0]) > 1){ // If theirs ties, filter again!
$sub_golfers =
array_intersect_key($golfers,
array_flip($winner[0])); // Only the Worthy Shall Pass.
$winner = getWinner($sub_golfers,$hole - 1); // And again...
}
return $winner; // We got a winner, unless they really tie...
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
Ok... Now ill explain my method...
Since we need to know the highest score and it might be ties, it makes no sense to me to maintain all that in separate arrays, instead I just reversed the
golfer => scores
to
Tota_score => golfers
That way when we can sort the array by key and obtain all the golfers with the highest score.
Now total_score is the total sum of a subset of the holes scores array. So... the first time this function runs, it will add all 9 holes, in this case theres 3 golfers that end up with the same score.
Array
(
[0] => Array
(
[0] => A
[1] => B
[2] => C
)
[1] => 35
)
Since the total count of golfers is not 1 and we are still in the 9th hole, we run this again, but this time only against those 3 golfers and the current hole - 1, so we are only adding up to the 8th hole this time.
Array
(
[0] => Array
(
[0] => B
[1] => C
)
[1] => 32
)
We had another tie.... this process will continue until we reach the final hole, or a winner.
Array
(
[0] => Array
(
[0] => C
)
[1] => 31
)
EDIT
<?php
/**
* Author : Carlos Alaniz
* Email : Carlos.glvn1993#gmail.com
* Porpuse : Stackoverflow example
**/
$golfers = [
"77" => [2,4,6,8,10,12,14,16,18],
"79" => [3,5,7,9,11,14,15,17,18],
"76" => [2,4,6,8,10,12,14,16,18],
"78" => [3,5,7,9,11,13,15,17,18]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
$positions = array(); // The score numer is the key!
foreach ($golfers as $golfer => $score) { // Get key and value
//$score_sub = array_slice($score,0,$hole); // Get the scores subset, first iteration is always all holes
$total_score = (string)$score[$hole-1]; // Get the key
if(!isset($positions[$total_score])){
$positions[$total_score] = array(); // Make array
}
$positions[$total_score][] = $golfer; // Add Golpher to score.
}
ksort($positions, SORT_NUMERIC); // Sort based on key, low -> high
return [
"winner"=> end($positions),
"score" => key($positions),
"tiebreaker_hole" => [
"hole"=>$hole,
"score"=> key($positions)],
]; // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
if ($hole == 0) return;
$highest = get_winners($golfers,$hole); // Get all ties, if any.
$winner = $highest;
if(count($winner["winner"]) > 1){ // If theirs ties, filter again!
$sub_golfers =
array_intersect_key($golfers,
array_flip($winner["winner"])); // Only the Worthy Shall Pass.
$winner = getWinner($sub_golfers,$hole - 1); // And again...
}
$winner["score"] = $highest["score"];
return $winner; // We got a winner, unless they really tie...
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
Result:
Array
(
[winner] => Array
(
[0] => 79
)
[score] => 18
[tiebreaker_hole] => Array
(
[hole] => 6
[score] => 14
)
)
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
This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Chunk and transpose a flat array into rows with a specific number of columns
(3 answers)
Closed 5 months ago.
So I have a database with players names and their skill level.
It looks like this:
Id | Name | Level
1 | Peter | 24
2 | Andy | 23
...
24 | John | 1
The first player in the list with the highest level is the strongest one, and the last is the weakest.
I need to sort them in groups with 4 players, so if I have 24 people there will be 6 groups.
The way I need to sort it I call "zig-zag".
It goes like this:
Ag Bg Cg Dg Eg Fg
01 02 03 04 05 06
12 11 10 09 08 07
13 14 15 16 17 18
24 23 22 21 20 19
So the A group will consist of players: 1, 12, 13, 24.
B group of players: 2, 11, 14, 23.
C group of players: 3, 10, 15, 22 and so on.
It's easy to do it by hand, but how I could automate this sort with PHP language?
The groups should be array list (I think so) which could I easily put to the group tables in database.
The idea would be to:
Sort your starting data (or preferably, start with it sorted).
Split it into chunks, basically one per each of your rows.
Reverse the order of every other chunk.
Flip the matrix so you've got your groups - one per column instead of one per row.
Example:
// Basic sample data.
$players = range(1, 24);
// Sort them ascending if you need to.
sort($players);
// Make a matrix. 2d array with a column per group.
$matrix = array_chunk($players, ceil(count($players)/4));
// Reverse every other row.
for ($i = 0; $i < count($matrix); $i++) {
if ($i % 2) {
$matrix[$i] = array_reverse($matrix[$i]);
}
}
// Flip the matrix.
$groups = array_map(null, ...$matrix); // PHP 5.6 with the fancy splat operator.
//$groups = call_user_func_array('array_map', array_merge([null], $matrix)); // PHP < 5.6 - less fancy.
// The result is...
print_r($groups);
Output:
Array
(
[0] => Array
(
[0] => 1
[1] => 12
[2] => 13
[3] => 24
)
[1] => Array
(
[0] => 2
[1] => 11
[2] => 14
[3] => 23
)
[2] => Array
(
[0] => 3
[1] => 10
[2] => 15
[3] => 22
)
[3] => Array
(
[0] => 4
[1] => 9
[2] => 16
[3] => 21
)
[4] => Array
(
[0] => 5
[1] => 8
[2] => 17
[3] => 20
)
[5] => Array
(
[0] => 6
[1] => 7
[2] => 18
[3] => 19
)
)