Fotios Tsakiris
Fotios Tsakiris

Reputation: 1556

Delete a subarray in an array in JavaScript using for loop

I need to delete a subarray if it has a particular element.

function filteredArray(arr, elem) {
  let newArr = [];
  for (let i = 0; i < arr.length; i++){
    for (let j = 0; j < arr[i].length; j++) {
      if (arr[i][j] === elem) {
        arr.splice(i--, 1);
        newArr = [...arr]
      }
    }
  }
  return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 19));

The code above works fine if the element is found just once (for ex. 19). But if I try number 3, I get: Uncaught TypeError: Cannot read property 'length' of undefined. Can someone please explain what is happening here?

Upvotes: 1

Views: 1260

Answers (3)

ggorlen
ggorlen

Reputation: 56905

The issue is that once you've spliced an item out of the array, your program continues iterating over the rest of the removed inner array as if it still existed. In the case of 3 as your target, every single inner array is removed because they all contain a 3. At the final removal, you detect a 3 at index 1 of the inner array and splice the last inner array. On the next iteration of the loop, the program crashes attempting to index into [0][2] in the empty array [].

The solution is to add a break statement as follows; this will abort further inspection of a removed array:

function filteredArray(arr, elem) {
  let newArr = [];
  
  for (let i = 0; i < arr.length; i++){
    for (let j = 0; j < arr[i].length; j++) {
      if (arr[i][j] === elem) {
        arr.splice(i--, 1);
        newArr = [...arr]
        break;
      }
    }
  }
  return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

Having said that, there are many simpler approaches you can take; for example, using array.filter(), which selects elements based on the truth value returned by its argument function:

const filteredArray = (a, target) => a.filter(e => !e.includes(target));

console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 19));

Upvotes: 1

Mark
Mark

Reputation: 92440

Using filter() with includes() is succinct enough you probably don't need a separate function:

let array = [[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]]
let filtered = array.filter(item => !item.includes(19));
console.log(filtered)

Upvotes: 3

user2575725
user2575725

Reputation:

Try Array.filter()

function filteredArray(arr, skip) {
  return arr.filter(function(sub) {
    return -1 === sub.indexOf(skip);
  });
}

var mixed = [[3, 2, 3], [1, 6, 2], [3, 13, 26], [19, 3, 9]];
console.log(filteredArray(mixed, 19));
console.log(filteredArray(mixed, 3));

Upvotes: 1

Related Questions