Auto-generate/loop a specific unordered list in PHP - php

I want to make something like this:
A1
B1
C1
D1
D2
D3
C2
C3
B2
C4
D10
D11
D12
C5
C6
B3
C7
C8
C9
D25
D26
D27
So it's always groups of three, with every level ascending by a letter. First level is A, second B, C, D, E and so forth. The numbers are also listed in ascending order. Level A can only reach 1, B has 3, C has 9, D has 27, and so forth.
This is really easy to generate manually, converting the letters to their ASCII equivalent, adding one and converting them to character equivalent again. Problem is, I have to loop it till S, for instance, and my mind is getting messier and messier trying to put loops within loops.
What I got (toLetter and toNumber literally does what they do):
echo "<ul><li>";
echo "A1";
echo "<ul><li>";
$b = toNumber(A);
$b++;
$b = toLetter($b);
$bnum = 1 - 1;
$bnum = $bnum * 3;
$bnum++;
echo $b;
echo $bnum."</li>";
$bnum++;
echo "<li>".$b;
echo $bnum."</li>";
$bnum++;
echo "<li>".$b;
echo $bnum."</li>";
Making this:
A1
B1
B2
B3
I really can't figure out how to just loop everything so it can reach till Z.

A pretty simple version which only goes up to the 'C' level; increase as necessary.
<?php
function outputListItems($char) {
static $index = array('A' => 1);
if (!isset($index[$char])) {
$index[$char] = 1;
}
for ($i = 0; $i < 3; $i++) {
echo '<li>';
echo $char;
echo $index[$char]++;
if ($char < 'C') {
echo '<ul>';
$nextChar = $char;
outputListItems(++$nextChar);
echo '</ul>';
}
echo '</li>';
}
}
?>
<ul>
<li>
A1
<ul><?php outputListItems('B'); ?></ul>
</li>
</ul>
A is treated as special chase, since it only has one entry.

in PHP, you can use ++ on a string, so you don't need to Letter/toNumber
And to support unlimited nesting, you need a recursion (or at least it will be easier for you)

Related

Why this unexpected behavior in pushing letters [a-z] in PHP? [duplicate]

<?php
for ($i = 'a'; $i <= 'z'; $i++)
echo "$i\n";
This snippet gives the following output (newlines are replaced by spaces):
a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az ba bb bc bd be bf bg bh bi bj bk bl bm bn bo bp bq br bs bt bu bv bw bx by bz ca cb cc cd ce cf cg ch ci cj ck cl cm cn co cp cq cr cs ct cu cv cw cx cy cz da db dc dd de df dg dh di dj dk dl dm dn do dp dq dr ds dt du dv dw dx dy dz ea eb ec ed ee ef eg eh ei ej ek el em en eo ep eq er es et eu ev ew ex... on to yz
From the docs:
PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's.
For example, in Perl 'Z'+1 turns into 'AA', while in C 'Z'+1 turns into '[' ( ord('Z') == 90, ord('[') == 91 ).
Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported.
From Comments:-
It should also be noted that <= is a lexicographical comparison, so 'z'+1 ≤ 'z'. (Since 'z'+1 = 'aa' ≤ 'z'. But 'za' ≤ 'z' is the first time the comparison is false.) Breaking when $i == 'z' would work, for instance.
Example here.
Because once 'z' is reached (and this is a valid result within your range, the $i++ increments it to the next value in sequence), the next value will be 'aa'; and alphabetically, 'aa' is < 'z', so the comparison is never met
for ($i = 'a'; $i != 'aa'; $i++)
echo "$i\n";
Others answers explain the observed behavior of the posted code. Here is one way to do what you want (and it's cleaner code, IMO):
foreach (range('a', 'z') as $i)
echo "$i\n";
In response to ShreevatsaR's comment/question about the range function: Yes, it produces the "right endpoint", i.e. the values passed to the function are in the range. To illustrate, the output from the above code was:
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
Others already said why PHP doesn't show what you expect. Here's how you get the result you might want:
<?php
for ($i = ord('a'); $i <= ord('z'); $i++)
echo chr($i);
?>
Why not just use range('a','z')?
Try this code. I think this code will be helpful to you.
$alphas = range('A', 'Z');
foreach($alphas as $value){
echo $value."<br>";
}
Display 26 letters in sequence.
<?php
$i = 'a';
do {
echo ($j=$i++),"\r\n";
} while (ord($j) < ord($i));
?>
Also this can be used:
for ($i = 'a'; $i <= 'z'; $i=chr(ord($i)+1))
echo "$i\n";
PHP has the function of looping letters and can exceed beyond single characters; the rest will be done this way: aa ab ac... zz, and so on.
Try this:
<?php
for ($i = 'a'; $i !== 'aa'; $i++)
echo "$i\n";
?>
While the above answers are insightful to what's going on, and pretty interesting (I didn't know it would behave like this, and its good to see why.
The easiest fix (although perhaps not the most meaningful) would be just to change the condition to $i != 'z'
<?php
for ($i = 'a'; $i != 'z'; $i++)
echo "$i\n";
?>
The PHP does not consider 'AA' less than 'Z'.
The best way to make this is:
for($i = 'a'; $i != 'aa'; $i++) {
echo $i;
}
abcdefghijklmnopqrstuvwxyz
Perhaps this code will work. It’s easy & can be understood:
<?php
$ascii_val = ord("a");
for($i=$ascii_val;$i<$ascii_val+26;$i++){
echo chr($i)."\n";
}
?>
where 26 is the total number of letters in the alphabet.
There are several ways to do that.
1. First you can take the range from 'a' to 'z'. Then iterate a loop over it.
foreach(range('a', 'z') as $i)
{
echo $i . "\n";
}
2. You can print the letters using asci value of the characters.
for($i = 97 ; $i<=122; $i++)
{
echo chr($i) . "\n";
}
3. You can take the asci value of 'a' and run a loop till the asci value of 'z':
for ($x = ord('a'); $x <= ord('z'); $x++)
{
echo chr($x) . "\n";
}
4. For printing a new line in html you can append the to the end of each characters.
for($i='a';$i<='z';$i++)
{
echo $i. "<br />";
}
this code will work. It’s easy & can be understood:
<?php
// print form A to ZZ like this
// A B C ... AA AB AC ... ZA .. ZZ
$pre = "";
$i = ord('a');
for ($x = ord('a'); $pre . strtoupper(chr($x-1)) != 'AH'; $x++)
{
echo "". $pre . strtoupper(chr($x)) . "\n";
if(chr($x) === "z"){
$pre = strtoupper(chr($i++));
$x = ord('a');
$x--;
}
}
One more way to get the display of characters a-z:
<?php
for ($i = 'a'; $i < 'z'; $i++){
echo "$i\n";
}
echo $i; // 'z'
See live code
Once the conditional loop becomes false, $i will have already been incremented and have the string value corresponding to 'z' which can be displayed.
Wow I really didn't know about this but its not a big code you can try echo "z" after loop Mark is Absolutely Right I use his method but if you want alternative then this may also you can try
<?php
for ($i = "a"; $i = "y"; $i++) {
echo "$i\n";
if ($i == "z") {}
}
echo "z";
?>

Generating a table that progresses vertically

I am currently generating a table in the following manner:
A0 A1 A2 A3
B0 B1 B2 B3
C0 C1 C2 C3
D0 D1 D2 D3
I'd like to do:
A0 B0 C0 D0
A1 B1 C1 D1
A2 B2 C2 D2
A3 B3 C3 D3
So basically make it progress vertically with 4 columns.
Current code:
<table cellspacing="2px">
<?php
# display products in 4 column table #
$i=0;
while ($data=mysqli_fetch_array($result)){
if($i > 0 and $i % 4 == 0) {
echo '<tr></tr>';
}
//passing id in link to retrieve product details
echo '<td>'.$data['name'].'</td>';
$i++;
}
?>
</table>
Can someone point me in the right direction to accomplish this?
Clarification
In the illustration above, I'm merely pointing out that I'd like to have the result progress vertically down and it also needs to expand to 4 columns (I've only shown 2 however it needs to expand to 4).
In the code snippet it progresses horizontally.
I have also updated the question to keep it simple.
I hope that clears any ambiguity.
This should do it.
<table>
<?php
$i = 0;
while ($data = mysql_fetch_array($result);
if ($i % 4 == 0) {
if ($i > 0) {
// End last row unless this is the first row
echo '</tr>';
}
// Start a new row
echo '<tr>';
}
echo '<td>...</td>';
$i++;
}
if ($i > 0) {
// Close out the last row, unless there wasn't any data
echo '</tr>';
}
?>
</table>
You had <tr></tr> backwards -- if you want to end one row and start a new one, it must be </tr><tr>. But the first row needs to be treated specially, since there's no previous row to end. If you know there will always be data, you can output the first <tr> and last </tr> unconditionally as part of the HTML code, but I wrote my code defensively.
Meh... who uses TABLES anymore? Do it with CSS! Very Easily done. Adjust my sample as needed.
<?
$x = 0;
$y = 0;
$count = 0;
$total = 100; // whatever your total is from sql result;
while ($count < $total) {
echo '<img src="foldername/'.$itempic[$count].'" style=\'postion:absolute;top:'.$y.'px;left:'.$x.'px;\'>'."\n";
$y = $y + 50;
if ($y > 300){
$y = 0;
$x = $x + 50;
}
$count++;
}
?>
Here is another example I made specifically for you:
Yes it is a bit gimp, but the logic is what you can glean from it and adjust it to your needs.
It does work though, I just wasn't going to take the time to make an example perfect.
<?
$info = Array(
A0,A1,A2,A3,
B0,B1,B2,B3,
C0,C1,C2,C3,
D0,D1,D2,D3);
$count = 0;
$total = 20;
$row = 0;
$col = 0;
while ($count < $total){
echo $info[$col+$row];
$col++;
$row = $row +3;
if($col > 4){
$col = 0;
$row = $row - 14;
echo '<br/>';}
$count++;
}
?>

Group array results in Alphabetic order PHP

I'm using below code to display Image & Name of webisites form database.
<fieldset>
<h1>A</h1>
<ul>
<?php foreach ($records as $key) { ?>
<li class="siteli"> <a href="#" class="add">
<div id="site-icon"><img src="<?php echo $key->site_img; ?>" width="16" height=""></div>
<p id="text-site"> <?php echo $key->site_name; ?></p>
</li>
<?php } ?>
</ul>
</fieldset>
Now I'm trying to group this results alphabetically by adding A, B, C etc as title.
Example,
A
Amazon
Aol
Aol Mail
B
Bing
Bogger
You can use array sorting to sort the array. In your case I would choose sort()
Now to show the links with a preceding Letter I would use:
<?php
$records = ['Aaaaa', 'Aaaa2', 'bbb', 'bbb2', 'Dddd'];
$lastChar = '';
sort($records, SORT_STRING | SORT_FLAG_CASE); //the flags are needed. Without the `Ddd` will come before `bbb`.
//Available from version 5.4. If you have an earlier version (4+) you can try natcasesort()
foreach($records as $val) {
$char = $val[0]; //first char
if ($char !== $lastChar) {
if ($lastChar !== '')
echo '<br>';
echo strtoupper($char).'<br>'; //print A / B / C etc
$lastChar = $char;
}
echo $val.'<br>';
}
?>
This will output something like
A
Aaaa2
Aaaaa
B
bbb
bbb2
D
Dddd
Notice that the C is missing, because there are no words starting with C.
This is a modification of #Hugo Delsing's answer.
I needed to be able to group my brands together like this, but one bug in the code was the fact that if I had say iForce Nutrition and Inner Armour it would group these into two separate groups because of the letter case.
Changes I Made
Because it was fully alphabetical, it was only going by first letter I changes SORT_STRING to SORT_NATURAL
Changed: if ($char !== $lastChar) to if (strtolower($char) !== strtolower($lastChar))
<?php
$records = ['FinaFlex', 'iForce Nutrition', 'Inner Armour', 'Dymatize', 'Ultimate Nutrition'];
$lastChar = '';
sort($records, SORT_NATURAL | SORT_FLAG_CASE); //Allows for a full comparison and will alphabetize correctly.
foreach($records as $val) {
$char = $val[0]; //first char
if (strtolower($char) !== strtolower($lastChar)) {
if ($lastChar !== '')
echo '<br>';
echo strtoupper($char).'<br>'; //print A / B / C etc
$lastChar = $char;
}
echo $val.'<br>';
}
?>
The final output will be like this
D
Dymatize
F
FinaFlex
I
iForce Nutrition
Inner Armour
U
Ultimate Nutrition
I hope this helps everyone, and a big thank you to Hugo for providing the code that got me exactly where I needed to be.
You can see my example here https://hyperionsupps.com/brand-index
$records = ['FinaFlex', 'iForce Nutrition', 'Inner Armour', 'Dymatize', 'Ultimate Nutrition'];
$temp=array();
$first_char="";
for($i=0;$i<count($records);$i++)
{
$first_char= strtoupper ($records[$i][0]);
if(!in_array($first_char, $temp))
{
echo strtoupper($first_char).'<br>'; //print A / B / C etc
}
$temp[]= $first_char;
echo $records[$i]."<br>";
}

Why doesn't this code simply print letters A to Z?

<?php
for ($i = 'a'; $i <= 'z'; $i++)
echo "$i\n";
This snippet gives the following output (newlines are replaced by spaces):
a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az ba bb bc bd be bf bg bh bi bj bk bl bm bn bo bp bq br bs bt bu bv bw bx by bz ca cb cc cd ce cf cg ch ci cj ck cl cm cn co cp cq cr cs ct cu cv cw cx cy cz da db dc dd de df dg dh di dj dk dl dm dn do dp dq dr ds dt du dv dw dx dy dz ea eb ec ed ee ef eg eh ei ej ek el em en eo ep eq er es et eu ev ew ex... on to yz
From the docs:
PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's.
For example, in Perl 'Z'+1 turns into 'AA', while in C 'Z'+1 turns into '[' ( ord('Z') == 90, ord('[') == 91 ).
Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported.
From Comments:-
It should also be noted that <= is a lexicographical comparison, so 'z'+1 ≤ 'z'. (Since 'z'+1 = 'aa' ≤ 'z'. But 'za' ≤ 'z' is the first time the comparison is false.) Breaking when $i == 'z' would work, for instance.
Example here.
Because once 'z' is reached (and this is a valid result within your range, the $i++ increments it to the next value in sequence), the next value will be 'aa'; and alphabetically, 'aa' is < 'z', so the comparison is never met
for ($i = 'a'; $i != 'aa'; $i++)
echo "$i\n";
Others answers explain the observed behavior of the posted code. Here is one way to do what you want (and it's cleaner code, IMO):
foreach (range('a', 'z') as $i)
echo "$i\n";
In response to ShreevatsaR's comment/question about the range function: Yes, it produces the "right endpoint", i.e. the values passed to the function are in the range. To illustrate, the output from the above code was:
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
Others already said why PHP doesn't show what you expect. Here's how you get the result you might want:
<?php
for ($i = ord('a'); $i <= ord('z'); $i++)
echo chr($i);
?>
Why not just use range('a','z')?
Try this code. I think this code will be helpful to you.
$alphas = range('A', 'Z');
foreach($alphas as $value){
echo $value."<br>";
}
Display 26 letters in sequence.
<?php
$i = 'a';
do {
echo ($j=$i++),"\r\n";
} while (ord($j) < ord($i));
?>
Also this can be used:
for ($i = 'a'; $i <= 'z'; $i=chr(ord($i)+1))
echo "$i\n";
PHP has the function of looping letters and can exceed beyond single characters; the rest will be done this way: aa ab ac... zz, and so on.
Try this:
<?php
for ($i = 'a'; $i !== 'aa'; $i++)
echo "$i\n";
?>
While the above answers are insightful to what's going on, and pretty interesting (I didn't know it would behave like this, and its good to see why.
The easiest fix (although perhaps not the most meaningful) would be just to change the condition to $i != 'z'
<?php
for ($i = 'a'; $i != 'z'; $i++)
echo "$i\n";
?>
The PHP does not consider 'AA' less than 'Z'.
The best way to make this is:
for($i = 'a'; $i != 'aa'; $i++) {
echo $i;
}
abcdefghijklmnopqrstuvwxyz
Perhaps this code will work. It’s easy & can be understood:
<?php
$ascii_val = ord("a");
for($i=$ascii_val;$i<$ascii_val+26;$i++){
echo chr($i)."\n";
}
?>
where 26 is the total number of letters in the alphabet.
There are several ways to do that.
1. First you can take the range from 'a' to 'z'. Then iterate a loop over it.
foreach(range('a', 'z') as $i)
{
echo $i . "\n";
}
2. You can print the letters using asci value of the characters.
for($i = 97 ; $i<=122; $i++)
{
echo chr($i) . "\n";
}
3. You can take the asci value of 'a' and run a loop till the asci value of 'z':
for ($x = ord('a'); $x <= ord('z'); $x++)
{
echo chr($x) . "\n";
}
4. For printing a new line in html you can append the to the end of each characters.
for($i='a';$i<='z';$i++)
{
echo $i. "<br />";
}
this code will work. It’s easy & can be understood:
<?php
// print form A to ZZ like this
// A B C ... AA AB AC ... ZA .. ZZ
$pre = "";
$i = ord('a');
for ($x = ord('a'); $pre . strtoupper(chr($x-1)) != 'AH'; $x++)
{
echo "". $pre . strtoupper(chr($x)) . "\n";
if(chr($x) === "z"){
$pre = strtoupper(chr($i++));
$x = ord('a');
$x--;
}
}
One more way to get the display of characters a-z:
<?php
for ($i = 'a'; $i < 'z'; $i++){
echo "$i\n";
}
echo $i; // 'z'
See live code
Once the conditional loop becomes false, $i will have already been incremented and have the string value corresponding to 'z' which can be displayed.
Wow I really didn't know about this but its not a big code you can try echo "z" after loop Mark is Absolutely Right I use his method but if you want alternative then this may also you can try
<?php
for ($i = "a"; $i = "y"; $i++) {
echo "$i\n";
if ($i == "z") {}
}
echo "z";
?>

PHP array collect

I have alphabet array 24 character: "A B C D E F G H I J K L M N O P Q R S T U V W X"
I want collect all case with: 3 unique characters.
First case: ABC, DEF, GHI, JKL, MNO, PQR, STU, VWX
This is a little late coming, but for anyone else reading over this: If you are looking to split a string into 3-character chunks, try PHP's built in str_split() function. It takes in a $string and $split_length argument. For example:
$alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWX';
$grouped = str_split($alphabet, 3);
var_export( $grouped );
This outputs the following array:
array ( 0 => 'ABC', 1 => 'DEF', 2 => 'GHI',
3 => 'JKL', 4 => 'MNO', 5 => 'PQR',
6 => 'STU', 7 => 'VWX', )
This works for the example given in the question. If you want to have every possible combination of those 24 letters, Artefacto's answer makes more sense.
There's a 1:1 relationship between the permutations of the letters of the alphabet and your sets lists. Basically, once you have a permutation of the alphabet, you just have to call array_chunk to get the sets.
Now, 24! of anything (that is 620448401733239439360000) will never fit in memory (be it RAM or disk), so the best you can do is to generate a number n between 1 and 24! (the permutation number) and then generate such permutation. For this last step, see for example Generation of permutations following Lehmer and Howell and the papers there cited.
$alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$c = strlen($alphabet);
$result = array();
for ($i = 0; $i < $c; ++$i) {
$current0 = $i;
for ($j = 0; $j < $c; ++$j) {
if ($current0 == $j) continue;
$current1 = $j;
for ($k = 0; $k < $c; ++$k) {
if (isset($current0 == $k || $current1 == $k)) continue;
$result[] = $alphabet[$i].$alphabet[$j].$alphabet[$k];
}
}
}
Hope I understood your question right. This one iterates over the alphabet in three loops and always skips the characters which are already used. Then I push the result to $result.
But better try the script with only five letters ;) Using alls strlen($alphabet) (don't wanna count now...) will need incredibly much memory.
(I am sure there is some hacky version which is faster than that, but this is most straightforward I think.)

Categories