The Modulo Operator for Alternating Rows
One common design feature is to have different visual treatments for alternating rows. As you iterate through a collection, you can use the modulo operator to determine if you're in an even or odd row.
In most languages, the modulo operator is the percent sign: %. Here's a quick example in PHP:
for($i=0;$i<10;$i++)
{
if($i % 2)
{
// I'm in an even row
}else{
// I'm in an odd row
}
}
The modulo is the remainder of doing a division. Dividing by 2 will have a remainder of only 0 or 1.
Conversation
Now why had I never thought of that before?
Still, I'd probably use it like this:
for($i=0; $i<10; $i++)
{
$class = 'row' . ($i % 2);
// code in here
}
and then define
.row0
and.row1
in my stylesheet.Wow...that's a hell of a lot easier than the way I've been doing it all these years.
Although using Smarty on most projects lately has simplified things.
Good tip!
Amazingly simple...how come I didn't think of that?
The modulus operator has been a handy odd/even determination tool for a very long time, I'm a little shocked people are only recently finding out about it (around here anyway).
Btw, it's not just for odd/even. You can do all sorts of cool stuff like figure out if it's a leap year, or any other repeating pattern like that.
Justin: I think you shouldn't be surprised for this. PHP has made it possible for a lot of non-programmers to easily create scripts. This is great because it helped spreading PHP all over the world, but it has been also a bad thing because it allowed the creation of bad-written scripts (personally I have been in the second category for long time). Therefore for me it's not surprising most people don't know about some simple PHP (dare I say programming) things like the modulus operator.
Very true flevour, I guess I lucked out. When I was a total newbie to server-side programming this was one of the first things that was taught to me (when I took a server-side programming class) so we could alternate row background colors.
I'm feeling very clever at having used this method for years.
What's the point in declaring a class for each row? Only the odd rows need a class to mark the exception e.g.
css:
table tr td {
background-color: #000;
color: #FFF;
}
table tr.alt td {
background-color: #FFF;
color: #000;
}
html:
<table>
<tr>...</tr>
<tr class="alt">...</tr>
</table>
There was nothing in the original post about putting a class on each row. Putting "alt" or something in every other row is pretty much standard.
Coming from ASP.NET, you code looks like hacking. In my web development world, there are simpler solutions.
For example, if we have a DataGrid (or table with a database behind, for those that aren't familiar with the ASP.NET slang), we'd have to write only:
Andrei: ASP.NET is simply an application framework. The underlying language still needs to determine alternate rows. Using Reflector on the
CreateControlHierarchy
of theDataGrid
object reveals these couple lines of code:As you can see, even Microsoft uses the modulo.
What about this?
I don't like to write a lot of unnecessary code as you can see :)
Em, I guess there seems to be something wrong with my comment. It eats up almost everything I write within the pre and code tags. What gives?
You have to remember to encode your <s and >s. :) I removed the duplicate post and fixed the encoding in your first comment.
I'm with Miha - using an operator with your PHP is much easier, and it's actually faster in my benchmarks.
This one is taken from the PHP manual:
$colours = array('#000000', '#808080', '#A0A0A0', '#FFFFFF');
// Get a colour
$color = next($colors) or $color = reset($colors);
(This example uses 4 colours)
I use this operator all the time in JavaScript to figure out leap year. Never thought about using it for alternate rows. Great tip!!
Jonathan, I was trying to show how sometimes things can be really simple on a not so popular platform (compared to LAMP).
There's nothing wrong (or degradating) with the modulo operator as far as I'm interested and I've used it plenty of times.
I woder if there is such thing as shifting in PHP. I remember that it was considered a better solution than using the modulo operator when speed was really an issue.
Thanks Jonathan :)
A quick note on the logic: if you want to test for an even number, you need to do
if (!$i % 2)
. If you want to test for an odd number, you need to doif ($i % 2)
.When first looking at Jonathan's code, I thought he'd got the logic the wrong way round. However, he sneakily started
$i
at 0, so when$i
is 0, we're on the 1st row. Thus an even$i
means an odd row number. So the logic needs to be backwards.It is certainly true that the modulo operator is '%' in most languages but making the assumption that 'most' means 'all' cost we about half an hour when, earlier in the week, I was trying to write the folowing code:
Duncan: yeah, I said most on purpose because I know that, for example, VBScript uses Mod. Great use of the mod operator in XSLT, btw.
Man...I read through all the comments and I can't believe how complicated things people use.
$nBgColor = 0
and then in the loop:
$nBgColor = 1 - $nBgColor
and use classes like row0 and row1 on tr. Subtraction is the fastest operation you can get.
I am with Justin P on this one. That was one of the first operators that we looked at 3 years ago in my first CS class.
Wesley: I actually sat on the fence about posting this because it seems pretty basic but as I have discovered previously, you can't assume everybody knows the same tricks you do. Not everybody learns to program through a computer science class. (I didn't... I just happened to learn from people who did!)
so coldfusion use the mod operator:
Heh, funny thing, I just explained this to a coworker. She didn't know about it and I was like: "What?!How can you not know this stuff??". And she was always saying how good she was at writing webapps in PHP...
i'm actually not a programmer so sorry if it might sound stupid.
i have a blog where i display cool ads from companies.
3 pictures per row and i want to have a
after every 3rd pic in a row.
you can check it out at www.brandinfection.com/ads
at the moment i'm using if($count == 3 || $count == 6...
very very silly i know but somehow this modulo thing doesn't work or i have to write it differently?
please help.
thanks a lot, nader
Hey nader,
You could probably do something like this:
if ($count % 3) {
/* The count is divisble by 3 evenly */
} else {
/* The count is not evenly divisible by 3 */
}
hi,
this script can also be written with bitwise operator '&', much faster than '%'.
for($i=0;$i<10;$i++){
if(1 & $i){
// I'm in an odd row
}
else{
// I'm in an even row
}
}
errata corrige:
for($i=0;$i<10;$i++){
if(1 & $i){
// I'm in an odd row
}
else{
// I'm in an even row
}
}
you improve the code of your 'post comment'.
seems to not like this:
$i<10;$i++
($i<10;$i++)
$n = 0; // row counter
while ($row = mysql_fetch_array($result))
{
$n++;
$n = $n&1;
print "<tr class=\"row$n\">
// et cetera
This code is probably slightly faster, if not quite as clean:
for($i=0;$i<10;$i++)
{
$j = (1 == $i) ? 0 : 1;
$class = 'row' . $j;
// code in here
}
This causes $j to 'flip' back and forth from 0 to 1 (in this case, starting with 1). To change $j from 0 to 1 it does a simple comparison, whereas doing a modulus calculation takes slightly more effort.
-- Kris Olhovsky
Nevermind, Aleksandar's method of subtraction is the best way.
(Fastest and still simple).
I use this technique:
// using a for loop
for($i=0;$i<10;$i++){
echo $i%2 ? 'odd' : 'even';
}
// using a while loop
$i = 0;
while(condition){
echo $i++%2 ? 'odd' : 'even';
}
If you're using classes, this is what I use:
while(loopingThroughWhatever)
{
$class = ($class == 'even') ? 'odd' : 'even';
}
To get something like this:
<div class="row_0">...</div>
<div class="row_1">...</div>
<div class="row_0">...</div>
<div class="row_1">...</div>
Using PHP, I use this method:
<?php
$num_classes = 2;
$i = 0;
while(condition){
?>
<div class="row_<?php echo $i++%$num_classes; ?>">...</div>
<?php } ?>
I like this method because it supports any number of alternating rows. Change '$num_classes' to however many alternating row classes you want.
Just a quick idea: Since this is a matter of frontend, I do the "odd-even"-thing with javascript. Just add to the className of every table-row an " odd" or " even" to make them show the way you want them.
Doing it the JS-way is pretty cool, because you don't have to worry in every loop on determing the row you are in. I use "moo.dom" to do the DOM-Exploring.
Just a thought!
Thanks - Nice Tip!
This is how I do it:
Gives you classes of row1, row2, row1...
Lots of short-hand methods and ternary operator examples given here, both are bad. You should always break down your conditional statements using curly braces for a couple of reasons..
1. It's more readable
2. If you ever need to do something else with that statement, it's easy to drop additions in (such as an 'elseif')
I only say this because like others, I've been using modulus for years, and there are times when I've had to go back and alter logic.
Mike: although I used an if/else statement in my example, I'm certainly not against using the ternary operator or other shorthand methods.
From a readable POV, it's marginal. From a refactoring POV, code refactoring happens and a ternary operator is barely going to slow me down and doesn't happen that very often.
I often have foreach loops in my PHP, and use associate arrays instead of numeric ones.
I personally think foreahcloops and assoc arrays are much more readable, so I prefer the example by Richard@Home, which doesn't require a numeric loop counter.
Too bad that my comment is at the bottom of the page, but oh well..
You know what's even faster than modulo? The logical and-operator.
for($i=0; $i<100; $i++) {
echo 'odd: ' . (($i & 1) ? 'yes':'no');
}
However, it only works on powers of two. Just substract 1 from a power of two (2-1) 1, (4-1) 3, (8-1) 7, etc.
It should be faster than modulo, even just a little bit. ;)
- Lick
Great example. This is very similar in Actionscript. Here is the code -
I use wordpress to run my blog. I initially used the mod approach for alternating rows. i went greedy, thinking, what about if I want say 4 styles...and each output to be displayed as floats ? So i came up with this.. You can extend the logic however...
Till a month ago I had this code in my theme, when I changed the skin again...
Hi there,
I'm a switch junky so I have been using this:
in conjunction with a loop for years. I never did a benchmark between conditionals and switches. Anyways looks like this subject was beat to heck but I thought I would share anyways. P.S. This should work out of the box. Bye.
I prefer oneliners:
And then:
position() works in for-each loops. In recursive loops it would be passed as a template param.