Reputation: 2143
The following loop groups the items into two groups: First group of 5 items in a li and then each group of 6 items. I'm trying to modify this to group first 3 items in a li and then next each 5 items in the li.
for ($i = 1; $i < 20; $i++) {
echo ($i === 1 || $i % 6 === 0) ? "<li>" : null,
"<div>item {$i}</div>",
($i % 6 === 5) ? "</li>" : null;
}
if ($i % 6 !== 0) echo "</li>";
I'm trying to modify to following, but the grouping does not work fine (eg. wrong number of items goes in a li, some items do not get in li etc.)
for ($i = 1; $i < 20; $i++) {
echo ($i === 1 || $i % 5 === 0) ? "<li>" : null,
"<div>item {$i}</div>",
($i % 5 === 3) ? "</li>" : null;
}
if ($i % 5 !== 0) echo "</li>";
Upvotes: 0
Views: 1433
Reputation: 4111
Try this (Edited):
echo "<li>";
for($i = 1; $i < 20; $i++) {
$mod = $i % 5;
echo $mod == 4 ? "<li>" : null,
"<div>item {$i}</div>",
$mod == 3 ? "</li>" : null;
}
if($i % 5 != 3) echo "</li>";
Code example with slight changes
Explanation:
If you want to group items in groups of 5, then mod by 5. The first three items are a special case, but since 3 is less than 5, we can incorporate the first three numbers into our main loop.
The problem with your code is in adding the <li>
s. Since we start $i
at 1 instead of 0, we should use $i % 5 == 4
instead of $i % 5 == 0
.
Upvotes: 1
Reputation: 38456
If I understand your desired output, you want something like (ignoring <div>
tags for brevity):
<li>item #1</li>
<li>item #2</li>
<li>item #3</li>
<li>
item #4
item #5
item #6
item #7
item #8
</li>
... repeat
If this is correct, and the numbers of items in each "rule" (rule being "first three" and "next five") could change (as they just did), I would recommend created variables to represent them - that way, in the future, you only have to change the variables and not worry about making actual code-changes.
The first method I'd recommend is a (semi)-full rewrite. This method uses a bunch of if
-statements in a way that I feel is more readable/manageable:
$firstGroupLength = 3;
$repeatedGroupLength = 5;
for ($i = 1; $i < 20; $i++) {
if ($i <= $firstGroupLength) {
echo '<li><div>item ' . $i . '</div></li>';
} else {
if ((($i - $firstGroupLength) % $repeatedGroupLength) == 1) {
echo '<li>';
}
echo '<div>item ' . $i . '</div>';
if ((($i - $firstGroupLength) % $repeatedGroupLength) == 0) {
echo '</li>';
}
}
}
if ((($i - $firstGroupLength) % $repeatedGroupLength) != 1) {
echo '</li>';
}
This method will get the job done, but is also a big on the longer side. However, if at any time in the future you want the first group to appear differently than the repeating group, say maybe with different a CSS class or some other random feature - this method lays it out on the table for you!
If you'd prefer to stick with your ternary operator method, the following should work just as well:
$firstGroupLength = 3;
$repeatedGroupLength = 5;
echo '<li>';
for($i = 1; $i < 20; $i++) {
echo ((($i % $repeatedGroupLength) == ($repeatedGroupLength - 1)) ? '<li>' : '')
. '<div>item ' . $i . '</div>'
. ((($i % $repeatedGroupLength) == $firstGroupLength) ? '</li>' : '');
}
if (($i % $repeatedGroupLength) != $firstGroupLength) echo '</li>';
In both of these methods, you will find a $firstGroupLength
variable. This is set to the first "group" of items that repeat by themselves (such as <li>item #</li>
). The second variable, $repeatedGroupLength
will set the number of elements that display in the repeating "item groups" blocks (such as <li>item # item # item #</li>
).
Upvotes: 1