I require a nested for loop for my php website which gives me results as follows.
I want to two integers incrementally - one stops at 12 and other continues until the specified values.
If one string is $i and second string is $j than I want output as:
$i 1 2 3 4 5 6 7 8 9 10 11 12
$j 1 2 3 4 5 6 7 8 9 10 11 12
$i 1 2 3 4 5 6 7 8 9 10 11 12
$j 13 14 15 16 17 18 19 20 21 22 23 24
$i 1 2 3 4 5 6 7 8 9 10 11 12
$j 25 26 27 28 29 30 31 32 33 34 35 36
It should be repeated up to n values.
You can try this:
<?php
createMatrix(40);
function createMatrix($jMax)
{
$jVal = 0;
while ($jVal < $jMax) {
// print line $i
echo ('$i' . "\t");
for ($iVal = 1; $iVal <= 12; $iVal++) {
echo "$iVal\t";
}
echo "\n";
// print line $j
echo ('$j' . "\t");
for ($j = 1; $j <= 12; $j++) {
$jVal++;
echo "$jVal\t";
if ($jVal === $jMax) {
echo "\n";
break;
}
}
echo "\n";
}
}
OUTPUT:
Im trying to make a table consist some sort of cinema seat from A[1-20] to J[1-20]. I have a txt file which contain seats that are reserved, like this:
A2;
A1;
A3;
A7;
if a seat is reserved, the bgcolor of table must be red. This is the full code:
<?php
$file = fopen($path,"r") or exit("cant open file");
$seat="";
while(!feof($file))
{
$seat.= fgets($file);
}
$seat_splitted = explode(";",$seat);
fclose($file);
$arrTable[]="";
$letter="";
$tableContent="";
for($i = 0,$counter=0;$i<10;$i++,$counter++)
{
if($i==0)
$letter="A";
else if($i==1)
$letter="B";
else if($i==2)
$letter="C";
else if($i==3)
$letter="D";
else if($i==4)
$letter="E";
else if($i==5)
$letter="F";
else if($i==6)
$letter="G";
else if($i==7)
$letter="H";
else if($i==8)
$letter="I";
else if($i==9)
$letter="J";
?>
<tr>
<?php
for($j = 1;$j<21;$j++)
{
$arrTable[$counter]= $letter.$j;
foreach($seat_splitted as $value)
{
if(strcmp($value,$arrTable[$counter])==0)
//if($value == $letter.$j)
{
$GLOBALS['color']="red";
break;
}
else
$GLOBALS['color']="white";
}
?>
<td bgcolor="<?php echo $GLOBALS['color']; ?>"> <?php echo $arrTable[$counter]?> </td>
<?php
$counter++;
}
?>
</tr>
<?php
}
?>
I dont know why when if(strcmp($value,$arrTable[$counter])==0) or //if($value == $letter.$j), its only catch the first seat which is "A2". But when i change the txt file to this:
A2;A1;A3;A7;
the IF can catch them all. Is it wrong to concatenate string like this? $seat.= fgets($file);. What can i do to make it work with the first txt file? Sorry for my bad english.
I think something like this should work for you. I simplified everything a bit.
1. First I create an array ($seats) with all seats in it. Which has a structure like this:
Array
(
[A] => Array
(
[1] => free
[2] => free
[3] => free
//...
//...
2. After this I get all reserved seats from the file into an array. (A better solution would be if you have all this data in a database!)
3. Then I loop through each reserved seat and also set it to that in the $seats array, so that it gets something like this:
Array
(
[A] => Array
(
[1] => reserved
[2] => free
[3] => reserved
//...
//...
4. At the end I simply print the table
Code:
<?php
//create seats
$rows = range(strtoupper("A"), strtoupper("J"));
$columns = range(1, 20);
$seats = array_combine($rows, array_map(function($v)use($columns){
return array_combine($columns, array_fill(0, count($columns), "free"));
}, $rows));
//get reserved seats
$reservedSeats = array_map(function($v){
return trim($v, ";");
}, file("test.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES));
//set reserved seats
foreach($reservedSeats as $reserved) {
$checkOne = preg_replace("/[^A-Z]*/", "", $reserved);
$checkTwo = preg_replace("/[^0-9]*/", "", $reserved);
if(isset($seats[$checkOne]) && isset($seats[$checkOne][$checkTwo]))
$seats[$checkOne][$checkTwo] = "reserved";
}
//print seats
$reservedColor = "red";
$defaultColor = "white";
$rowColor = "green";
echo "<table border='1'>";
foreach($seats as $row) {
echo "<tr><td bgcolor='" . $rowColor . "'>" . $rowKey . "</td>";
foreach($row as $key => $seat)
echo "<td bgcolor='" . ($seat == "reserved"?$reservedColor:$defaultColor) . "'>" . $key . "</td>";
echo "</tr>";
}
echo "</table>";
?>
output (without colors):
A 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
C 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
F 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
G 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
H 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
IF you use the explode as you do, you will get an array of:
["A2","\nB1","\nC3"...]
So you have to deal with the \n
Maybe you could have a try as explode(";\n",$seat)
Update: in some system u need to use \r\n. So here is the correct final solution: explode(";\r\n",$seat)
How do i create a nested loop that will output the following numbers?
each round the inner loop increase from 1 to 5, 5 to 10 and so on.
from i = 0 to 5
inner loop:
result: 1 2 3 4 5
result: 6 7 8 9 1 0
result: 11 12 13 14 15
result: 16 17 18 19 20
next
for($i=0;$i<50;$i++)
{
$s = $i +5;
echo $s;
}
unless you have to use an inner do...while loop, this will work:
<?php
$max = 5;
for($i=0;$i<$max;$i++){
for($j=1;$j<=$max;$j++){
echo str_pad(($i*$max)+$j,4);
}
echo "\r\n";
}
output:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
I used str_pad() just to make the columns more uniform
Hi I have a 1D array (1 by 20) that I would like to transform to a 2D Array (4 by 5)
$winning_number = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
to
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
right now I am using this code:
foreach ($wining_no as $boulex)
{
for($i=0;$i<$5;$i++)
{
if($i==0)
{
for($j=0;$j<$4;$j++)
{
$boule_array[$j][$i] = $boulex;
}
}
}
}
For some reason this does not work
You could use the array_chunk($array, $size) function
For you it would be like this
array_chunk($winning_number, 5);
How I can change this:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 11
[8] => 21
[9] => 22
[10] => 23
[11] => 24
)
To this:
1-7, 11, 21-24
I have a list of numbers like this in PHP array, and I just want to make this list a little bit smaller.
2000: 3 6 7 11 15 17 25 36 42 43 45
2001: 2 3 4 5 6 9 10 11 12 13 34 37 45 46 47 48 49 50 51 52
2002: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 33 34 35 36 37 39 40 41 42 43 44 45 46 47 48 49 50 51 52
2003: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
2004: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 21 22 23 24 25 26 27 28 29 30 31 32 33 34 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
2005: 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
2006: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
2007: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
Interesting task.
Here's a demo script that does exactly what you want.
Tweak to taste.
Code
<?php
$groups = array();
$active_group = 0;
$output = array();
$output_counter = 0;
$nums = array( 1, 2, 3, 4, 5, 6, 7, 11, 21, 22, 23, 24 );
foreach( $nums as $k => $num ) {
// if this isn't the first item, and the current number
// isn't one more than the previous one, increment the counter
if( $k !== 0 && $nums[$k] !== $nums[$k-1]+1 )
$active_group ++;
// add this number to a group
$groups[ $active_group ][] = $num;
}
// take the 1st and last of each group
foreach( $groups as $group ) {
$first = array_shift( array_values($group) );
$output[$output_counter][] = $first;
$last = array_pop( array_values($group) );
if( $first !== $last )
$output[$output_counter][] = $last;
$output_counter++;
}
echo '<pre>';
print_r($output);
?>
Output
Array
(
[0] => Array
(
[0] => 1
[1] => 7
)
[1] => Array
(
[0] => 11
)
[2] => Array
(
[0] => 21
[1] => 24
)
)
A single loop will do. You need need to keep track of the "previous" iteration's value and the "starting" value for storing ranged data.
Code:
$prev = -1; // initialize out of range
foreach ($numbers as $n) {
if (!isset($start)) { // first iteration
$start = $n; // declare $start
} elseif ($n != $prev + 1) { // not consecutive
$result[] = $start == $prev ? $prev : "$start-$prev"; // store single or ranged values
$start = $n; // update $start
}
$prev = $n; // declare / update $prev
}
$result[] = $start == $prev ? $prev : $start . '-' . $prev; // store final iteration data
echo implode(', ', $result); // comma delimit the values
Output from: $numbers = [1, 2, 3, 4, 5, 6, 7, 11, 21, 22, 23, 24]; (Demo)
1-7, 11, 21-24
Output from: $numbers = [1, 3, 5, 6, 11, 21, 22, 23, 24, 26]; (Demo)
1, 3, 5-6, 11, 21-24, 26
Here is a way to both compress an array of integers into the string format you want and to expand that string format back out to an array of integers.
function compress($expanded) {
$low = -1;
$prevNum = -1;
$expanded = array_unique($expanded);
sort($expanded, SORT_NUMERIC);
foreach($expanded as $num) {
if($low == -1) {
$low = $num;
} else if($num - $prevNum > 1) {
$compact[] = ($prevNum - $low >= 1) ? sprintf("%d-%d", $low, $prevNum) : $prevNum;
$low = $num;
}
$prevNum = $num;
}
if($low != -1 ) {
$compact[] = ($num - $low >= 1) ? sprintf("%d-%d", $low, $num) : $num;
}
return implode(",", $compact);
}
public static function expand($compact) {
$expanded = Array();
$compact = explode(",", $compact);
foreach($compact as $num) {
if( is_numeric($num) ) {
$expanded[] = $num;
} else {
list($low, $high) = explode("-", $num);
if( is_numeric($low) && is_numeric($high) && $low < $high) {
for($i = $low;$i <= $high;$i++) {
$expanded[] = $i;
}
}
}
}
return $expanded;
}
//Placeholder array
$b = array();
// Slice array (where to slice)
$s = array(11, 21);
foreach ($array as $year => $a) {
for($i = 0; $i < count($a); $i++) {
for($ii = 0; $ii < count($s); $ii++) {
if($i == 0) {
$b[$year]['<' . $s[$ii]][] = $a[$i];
break;
} else if ( isset($a[$i+1]) && $a[$i] < $s[$ii] && $a[$i+1] >=$s[$ii]){
$b[$year]['<' . $s[$ii]][] = $a[$i];
if (isset($s[$ii+1])) {
$b[$year]['<' . $s[$ii+1]][] = $a[$i+1];
} else {
$b[$year]['>' . $s[$ii]][] = $a[$i+1];
}
break;
} else if ( !isset($s[$ii+1]) && $i == count($a) - 1) {
$b[$year]['>' . $s[$ii]][] = $a[$i];
break;
}
}
}
}
$array
The list of numbers
OUTPUT ($b):
array
2000 =>
array
'<11' =>
array
0 => int 3
1 => int 7
'<21' =>
array
0 => int 11
1 => int 17
'>21' =>
array
0 => int 25
1 => int 45
2001 =>
array
'<11' =>
array
0 => int 2
1 => int 10
'<21' =>
array
0 => int 11
1 => int 13
'>21' =>
array
0 => int 34
1 => int 52
2002 =>
array
'<11' =>
array
0 => int 1
1 => int 10
'<21' =>
array
0 => int 11
1 => int 20
'>21' =>
array
0 => int 21
1 => int 52
2003 =>
array
'<11' =>
array
0 => int 1
1 => int 10
'<21' =>
array
0 => int 11
1 => int 20
'>21' =>
array
0 => int 21
1 => int 51
2004 =>
array
'<11' =>
array
0 => int 1
1 => int 10
'<21' =>
array
0 => int 11
1 => int 19
'>21' =>
array
0 => int 21
1 => int 52
2005 =>
array
'<11' =>
array
0 => int 1
1 => int 10
'<21' =>
array
0 => int 11
1 => int 20
'>21' =>
array
0 => int 21
1 => int 52
2006 =>
array
'<11' =>
array
0 => int 1
1 => int 10
'<21' =>
array
0 => int 11
1 => int 20
'>21' =>
array
0 => int 21
1 => int 52
2007 =>
array
'<11' =>
array
0 => int 1
1 => int 10
'<21' =>
array
0 => int 11
1 => int 20
'>21' =>
array
0 => int 21
1 => int 52
NOTE: Just change the values (11) and (21) to suit your needs. You can add more values.
Heres an example:
$query = "SELECT '1-11' Range, COUNT(rank) rank
FROM promoted WHERE rank between 1 and 11
union all
SELECT '12-21' Range, COUNT(rank) rank
from promoted
where rank between 12 and 21
union all
SELECT '22-31' Range, count(rank) rank
from promoted
where rank between 22 and 31
union all
SELECT '32-40' Range, count(rank) rank
from promoted
where rank between 22 and 31
union all
SELECT rank, count(rank) FROM promoted WHERE rank = '40'";