Search code examples
javascriptarrayssplice

Javascript's "splice" method strange behavior


I was trying to solve some of the programming challenges at "free code camp" website, The problem was to find the symmetric difference between multiple arrays and returning an array of the symmetric difference of the provided arrays.

for example the following arrays:

[1, 2, 5], [2, 3, 5], [3, 4, 5]

should return [ 1, 4, 5 ]

so that's what I came up with:

function sym() {
  var final = [];
  var current_array = [];

  for (var i = 0; i < arguments.length; i++) {
    current_array = arguments[i];
    //ensures duplicates inside each array are removed first
    current_array = current_array.filter(function (element, index) {
      return current_array.indexOf(element) == index;
    });

    for (var j = 0, end = current_array.length; j < end; j++) {
      if(final.indexOf(current_array[j]) < 0)
        final.push(current_array[j]);
      else
        // for some reason "splice" isn't working properly..
        // final.splice(final.indexOf(current_array[j], 1));
        delete final[final.indexOf(current_array[j])];
    }
  }

  var final_2 = [];
  // Removing the empty slots caused by the "delete" keyword usage
  for (var m = 0; m < final.length; m++) {
    if(typeof final[m] !== 'undefined')
      final_2.push(final[m]);
  }
  return final_2;
}

in the previous logic I created an array called final that is supposed to hold all of the elements that only exist once in all of the passed arrays, firstly I loop over the arguments parameter which represents here the arrays and for each array I loop over its elements and check if that element exists in the final array or not. If it exists I remove it from the final array, else I push it to the array.

The problem here is if I use the splice method as given in the code above, it behaves very strangely, for example for the following arrays

[1, 2, 3], [5, 2, 1, 4], the result should be: [3, 5, 4]

when I use this line

final.splice(final.indexOf(current_array[j], 1));

instead of

delete final[final.indexOf(current_array[j])];

and return the final array it returns this [ 4 ]

here is the array values at each iteration

round (0, 0): 1
round (0, 1): 1,2
round (0, 2): 1,2,3
round (1, 0): 1,2,3,5
round (1, 1): 1
round (1, 2):
round (1, 3): 4

once it gets to an element that exists in the array it removes all of the elements starting from this element until the end of the array.

I don't know exactly if I'm missing something, I tried to search for any similar problems but most of what I came up with was a problem of removing elements from an array that the person was looping over and hence missing with its indices .. In my case the array I'm trying to modify got nothing to do with the arrays I'm iterating through. Also I believe splice modifies the array in place and returns the removed elements.. please correct me if I'm not getting it well.


Solution

  • You've misplaced a ), here's the correction:

    final.splice( final.indexOf(current_array[j]), 1 );
    

    An additional note: the algorithm adds 5 for the first array, removes it for the second, and adds it again for the third (since it isn't present in final anymore), resulting in [1,4,5]. With an odd number of arguments, the value is preserved, with an even number, it is removed.

    A simpler way to get all unique values from all arrays (if that is the intent), is to count the occurrences and filter on a single occurrence:

    function sym2() {
      var count = {};
      for ( var i in arguments ) {
        console.log("Processing ", i );
        for ( var k = 0; k < arguments[i].length; k ++)
          count[ arguments[i][k] ] = (count[ arguments[i][k] ]||0) + 1;    
      }
      var final = [];
      for ( var i in count )
        if ( count[i] == 1 )
          final.push( i );
      return final;
    }
    sym2([1, 2, 5], [2, 3, 5], [3, 4, 5]);

    Note that this will return [1,4] rather than [1,4,5].