Search code examples
javascriptarraysin-place

JavaScript mutating arrays in loop


I want to duplicate certain arrays in arrays using JavaScript, for example:

var res = [["1,2,3",100,50],["4,5",75,10],["6",20,90]];
var res2 = [];
for(var z in res) {
  var row = res[z];
  var keys = row[0].split(',')
  for(var y in keys) {
    var key = keys[y];
    res2.push([key,row[1]/keys.length,row[2]/keys.length]);
  }
}
/* 
[ [ '1', 33.333333333333336, 16.666666666666668 ],
  [ '2', 33.333333333333336, 16.666666666666668 ],
  [ '3', 33.333333333333336, 16.666666666666668 ],
  [ '4', 37.5, 5 ],
  [ '5', 37.5, 5 ],
  [ '6', 20, 90 ] ]
*/

The arrays are really-really long, is it possible to do this in-place (res, without res2)?


Solution

  • You can use splice for a true in-place processing of res:

    for (var i = 0; i < res.length; ) {
      var row = res[i];
      var keys = row[0].split(',')
      res.splice(i, 1); // Remove old element
      // Insert new elements at current position
      for (var j in keys)
        res.splice(i++, 0, [keys[j], row[1] / keys.length, row[2] / keys.length]);
    }
    

    Result:

    [
     ["1", 33.333333333333336, 16.666666666666668],
     ["2", 33.333333333333336, 16.666666666666668],
     ["3", 33.333333333333336, 16.666666666666668],
     ["4", 37.5, 5],
     ["5", 37.5, 5],
     ["6", 20, 90]
    ]
    

    EDIT:

    Another trick to avoid splices is to extend the size of res and start filling it from the end to the beginning:

    var n = res.length;
    
    // Precalculate new length
    var length = 0;
    for (var i = 0; i < res.length; i++)
        length += res[i][0].split(',').length;
    
    // Change length of array
    res.length = length;
    
    // Start filling from end to start
    for (var i = n - 1, k = length - 1; i >= 0; i--) {
        var row = res[i];
        var keys = row[0].split(',');
        for (var j = keys.length - 1; j >= 0; j--)
            res[k--] = [keys[j], row[1] / keys.length, row[2] / keys.length];
    }