1

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?

3 Answers 3

3

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)

Sign up to request clarification or add additional context in comments.

Comments

1

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));

1 Comment

Thanks a lot for the explanation and the solution to the code i provided. :) Of course I will go with filter.
1

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));

2 Comments

better logic employed here
Arvind, thanks for the nice solution and concise code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.