Search code examples
javascriptloopsreusabilityhigher-order-functions

How do I reuse a for-loop where an array is indexed differently each time


So, I have a piece of code inside a switch statement that is being repeated almost exactly in each case section. The code for the first case looks like follows:

// Some working arrays being defined in each case
countArr = createArrWithZeroes(height);
processArr = createEmpty2DArr(width, height);

for (j = 0; j < height; j++) {
    for (k = 0; k < width; k++) {
        item = arr[j][k];
        if (item !== null) {
            // Accessing the working arrays, note the indexing
            processArr[j][countArr[j]] = item;
            countArr[j]++;
        }
    }
}

And in the next case I have:

countArr = createArrWithZeroes(width);
processArr = createEmpty2DArr(width, height);

for (j = 0; j < height; j++) {
    for (k = 0; k < width; k++) {
        item = arr[j][k];
        if (item !== null) {
            processArr[countArr[k]][k] = item;
            countArr[k]++;
        }
    }
}

And so on, with each case having different indexing being used inside the two for loops. Note that the countArr is also defined differently between the two.

I feel like this block of code can be abstracted so that it can be reused, but I'm not sure how to do it. I can move the switch statement inside the for blocks, but the problem is that the countArr array also needs to be defined differently for each case. So then I'd end up with two switch statements, one of which is inside two for loops (doesn't seem great). Is there a way to solve this with higher-order functions?


Solution

  • You could encapsulate your looping code in a function. Write it so that it can accept a callback function; this callback would allow you to pass-in the differing piece of code e.g.

    // First callback- This has the code found in your first nested for statement
    var itemFunctionOne = function(processArr,index,countArr,item) {
     processArr[index][countArr[index]] = item;
    };
    
    // Second callback- This has the code found in your second nested for statement
    var itemFunctionTwo = function(processArr,index,countArr,item) {
     processArr[countArr[index]][index] = item;
    };
    
    // Encapsulate your looping code in a function. Write it so that it can accept a callback function.
    var itemProcessor = function(itemFunction) {
     countArr = createArrWithZeroes(height);
     processArr = createEmpty2DArr(width, height);
    
     for (j = 0; j < height; j++) {
      for (k = 0; k < width; k++) {
          item = arr[j][k];
          if (item !== null) {
              // Accessing the working arrays, note the indexing
              itemFunction();
              countArr[j]++;
          }
      }
     }
    }
    
    // You could  then call this in your switch statement
    itemProcessor(itemFunctionOne)
    
    // ...and this
    itemProcessor(itemFunctionTwo)
    

    Because objects (and hence arrays) in JavaScript are passed by reference, the callback functions will work as expected.

    Note that I haven't tested the code above!

    I've written a really simple example of this pattern in action here