javascriptarraysgeneralization

In how many ways can this function be simplified?


I'm trying to simplify/generalize a function foo_one that traverses through a multidimensional array and sets all sub-array elements apart from the first one to have null values.

I was given only the first function, for which I should then find more ways to generalize it to still accomplish the intended purpose of foo_one.

Any suggestions would be highly appreciated.

I've already implemented 2 other variations of the function and I like to have more if possible.

var arr = [
  [2, null, 2, null],
  [2, null, 2, null],
  [null, null, null, null],
  [null, null, null, null]
];

function foo_one() {
  for (let y = 0; y < arr.length - 1; y++) {
    for (let x = 0; x < arr.length - 1; x++) {
      if (arr[x + 1][y] != null) {
        if (arr[x + 1][y] == arr[x][y]) {
          arr[x][y] = arr[x][y] * 2;
          arr[x + 1][y] = null;
        }
        if (arr[x][y] == null) {
          arr[x][y] = arr[x + 1][y];
          arr[x + 1][y] = null;
        }
      }
    }
  }
}

function foo_two() {
  for (let y = 0; y < arr.length - 1; y++) {
    for (let x = 0; x < arr.length - 1; x++) {
      if (arr[x + 1][y] != null && arr[x + 1][y] == arr[x][y]) {
        arr[x][y] = arr[x][y] * 2;
        arr[x + 1][y] = null;
      }
    }
  }
}

function foo_three() {
  for (let y = 0; y < arr.length - 1; y++) {
    for (let x = 0; x < arr[y].length - 1; x++) {
      if (arr[x + 1][y] != null && arr[x + 1][y] == arr[x][y]) {
        arr[x][y] = arr[x][y] * 2;
        arr[x + 1][y] = null;
      }
    }
  }
}

// Output
[ [ 4, null, 4, null ],
  [ null, null, null, null ],
  [ null, null, null, null ],
  [ null, null, null, null ] ]

Solution

  • function foo_four(arr) {
       let yLoopCount = arr.length - 1,
           xArrLength = 0,
           currentRowValue = 0,
           nextRowValue = 0;
    
       for (let y = 0; y < yLoopCount; y++) {
         xArrLength = arr[y].length;  // arr[y].length - 1
    
         for (let x = 0; x < xArrLength; x++) {
           currentRowValue = arr[y][x];
           nextRowValue  = arr[y+1][x];
    
           if (currentRowValue && currentRowValue == nextRowValue) {
             arr[y][x] = currentRowValue * 2;
             arr[y+1][x] = null;
           }
        }
    
      return arr;
    }
    
    
    var arr = [
      [2, null, 2, null],
      [2, null, 2, null],
      [null, null, null, null],
      [null, null, null, null]
    ];
    
    foo_four();
    
    // Output
    // [
    //     [4, null, 4, null],
    //     [null, null, null, null],
    //     [null, null, null, null],
    //     [null, null, null, null]
    // ];
    

    a) I'm looping through the last row as well.
    b) It's a minor optimization if you create the variables outside the loop, and then reuse them.
    c) It's a minor optimization if you're using variables to shorten any kind of deep reference. Diving into each subproperty takes time, like referencing arr[y][x] several times instead of currentRowValue.
    d) I prefer to send the array as a parameter, and also return it, even if I change the array. Cleaner code in my book, and easier to debug.
    e) Use variable (or method) names to explain what's going on.
    f) By using variables, it's easier to debug.
    g) I usually give all variables a starting value to describe what kind of type they are (empty array, object, number, string) so the next person can look at them and see what they are without having to read and process what the variable names means.