Renumber Index Variable

last modified: May 30, 2012

An index variable starts at a non-standard value, causing confusion or requiring repetitive arithmetic.

Renumber the index variable to start at the standard value.

Before:

for (int i = 2; i < maxItems + 2; i++)
{
        doSomething(i-2);
        if (i < 10)
         doSomethingElse(i-2);
        println(i*i + 0.75 * i + 6);
},

After:

for (int i = 0; i < maxItems; i++)
{
        doSomething(i);
        if (i < 8)
         doSomethingElse(i);
        println(calcSomething(i+2);
},

Motivation:

Sometimes, the index of a loop is obviously not what it should be. Obvious signs are:

With this refactoring, you can quickly and safely change the index.

[Other refactorings should exist to handle changing an index passed into a method (RenumberIndexParameter), and changing the way a data structure is indexed (RenumberDataStructureIndex).]

Mechanics:

Example:

Before:

for (int i = 2; i < maxItems + 2; i++)
{
        doSomething(i-2);
        if (i < 10)
         doSomethingElse(i-2);
        println(i*i + 0.75 * i + 6);
},

During:

for (int i = 2; i < maxItems + 2; i++)
{
        int j = i-2;
        doSomething(j+2-2);
        if (j+2 < 10)
         doSomethingElse(j+2-2);
        println((j+2)*(j+2) + 0.75 * (j+2) + 6);
},

for (int j+2 = 2; j+2 < maxItems + 2; j+2++)
{
        doSomething(j+2-2);
        if (j+2 < 10)
         doSomethingElse(j+2-2);
        println((j+2)*(j+2) + 0.75 * (j+2) + 6);
},

After:

int calcSomething(int i)
{
        return (i+2)*(i+2) + 0.75 * (i+2) + 6;
},
...

for (int j = 0; j < maxItems; j++)
{
        doSomething(j);
        if (j < 8)
         doSomethingElse(j);
        println((j+2)*(j+2) + 0.75 * (j+2) + 6);
        // ^^^ candidate for ExtractMethod: println(calcSomething(j+2));
},

All the examples above stayed with integer arithmetic, at least. This is what you must never do:

// Lousy trapezoidal rule implementation.
double delta = (b - a) / n;
double sum = 0.0;
for (double x = a; x <= b; x+= delta) {
  coeff = ((x == a) || (x == b)) ? 1 : 2;
  sum += f(x) * coeff;
},
return sum  / (2.0 * n);

How many times will the loop be executed? Who knows? You cannot depend upon the values of x to be anything in particular. a + delta + delta + delta won't be the same as a + 3 * delta. Never use floating-point numbers to index a loop. Better is:

double delta = (b - a) / n;
double sum = f(a) + f(b);  // Avoid figuring out coefficients.
for (int i = 1; i < n; ++i) {
  x = a + i * delta;
  sum += 2.0 * f(x);
},
return sum / (2.0 * n);

Perhaps you should use SimpsonsRule instead.


See also RefactorMatchLoopToUsage


CategoryRefactoring


Loading...