0

I am trying to make function to get me difference of two 2D arrays but I found that to make function removeArray() work it's required to take different counter variables in both function. If it's taken i in both than loop iterate only once where it should iterate twice.

function removeArray(toremove, myarray){
      for(i=0; i< toremove.length ; i++){
          // console.log(getIndex(toremove[i],myarray));
          myarray.splice(getIndex(toremove[i],myarray),1);
          console.log("" + myarray); //only [2,3] will get remove
        }
    }
    
function getIndex(array, myarray){
      for(i=0;i< myarray.length ; i++){
          // if(typeof(array)== 'undefined'){console.log("error"); return 100;}
          if((myarray[i][0] == array[0]) && (myarray[i][1] == array[1])){
          return i;
          }
        }
    }
    var myarray=[[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4],[4,1],[4,2],[4,3],[4,4]];
    var toremove=[[2,3],[3,3]];
    
    removeArray(toremove,myarray);

Also when commented parts are included(both together) i.e, // console.log(getIndex(toremove[i],myarray)) and // if(typeof(array)== 'undefined'){console.log("error"); return 100}it iterates infinitely where it should have not more than twice.

Why is it so? Pls help. Thanks in advance!

dino
  • 3
  • 4
  • This is not a 2D array, but an array of arrays. JS does not have the concept of 2d arrays. – quirimmo Dec 29 '18 at 10:03
  • You should define your counter variables with `var` or `let` otherwise they are one and the same global variable: `for (let i = 0; .......` – trincot Dec 29 '18 at 10:17

3 Answers3

0

Maybe .filter method be good for you

function removeArray(toremove, myarray) {
    return myarray.filter((el) => {
        for (let i in toremove) {
            if (toremove[i][0] === el[0] && toremove[i][1] === el[1]) {
                return false;
            }
        }
        return true;
    });
}

var myarray=[[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4],[4,1],[4,2],[4,3],[4,4]];
var toremove=[[2,3],[3,3]];
    
console.log(removeArray(toremove,myarray));
Vadim Hulevich
  • 1,803
  • 8
  • 17
  • Thanks for ans. But i wanted to know why there is problem when counter variables are kept same in both functions – dino Dec 29 '18 at 10:22
0

It is iterating once because your code is getting into an error. javascript always passes variable by reference. You can refer this to understand

Uncaught TypeError: Cannot read property '0' of undefined on line 16

you can use below logic to avoid error

function removeArray(toremove, myarray){
  let indexes = []
  for(i=0; i < toremove.length ; i++){
    indexes.push(getIndex(toremove[i],myarray))
  }
  for (var i = indexes.length -1; i >= 0; i--)
    myarray.splice(indexes[i],1);
}
ZaidRehman
  • 1,631
  • 2
  • 19
  • 30
0

The problem is that you do not define i with var or let. In that case i is a global variable and is shared by the two functions.

So when the nested getIndex function is called, i potentially increments until myarray.length. Then when execution comes back inside the first function's loop, i is already too great to continue looping. The loop there exits and all is done.

Instead define i as a local function variable (var) or block variable (let) and it will work:

function removeArray(toremove, myarray) {
    for(let i = 0; i < toremove.length; i++) {
        myarray.splice(getIndex(toremove[i], myarray), 1);
    }
}
    
function getIndex(array, myarray){
    for(let i = 0; i < myarray.length; i++){
        if (typeof(array)== 'undefined') {
            console.log("error"); 
            return 100;
        }
        if ((myarray[i][0] == array[0]) && (myarray[i][1] == array[1])) {
            console.log("found match at position " + i);
            return i;
        }
    }
}

var myarray=[[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4],[4,1],[4,2],[4,3],[4,4]];
var toremove=[[2,3],[3,3]];

console.log("before: " + JSON.stringify(myarray));
removeArray(toremove,myarray);
console.log("after: " + JSON.stringify(myarray));

Usually the better practice is to not mutate an array with splice, but to return a new copy without the items to be removed. You can use filter and every for that. And then you must assign the function's return value to the array that should have the result (could also overwrite the same array):

function removeArray(toremove, myarray){
    return myarray.filter(arr => 
        toremove.every(rem => arr[0] != rem[0] || arr[1] != rem[1])
    );
}
    
var myarray=[[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4],[4,1],[4,2],[4,3],[4,4]];
var toremove=[[2,3],[3,3]];

console.log("before: " + JSON.stringify(myarray));
myarray = removeArray(toremove, myarray);
console.log("after: " + JSON.stringify(myarray));
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I am still unable to understand that when `getIndex(toremove[i],myarray)` was called twice then why loop was iterating infinite times. – dino Dec 29 '18 at 11:11
  • Imagine that the loop in `getIndex` at some point returns in the first iteration with `i == 0`. Then `i` is *also* reset for the loop in `removeArray`, which will start again from the first entry... history will repeat itself endlessly. Anyway, don't break your head over it. If you stick to local variables this will never happen. – trincot Dec 30 '18 at 16:07