Is there a better solution for Iterate Through All an Array's Items Using For Loops?

Tell us what’s happening:
I solved this problem technically with no problem. But is there a more efficient solution within the context of the problem (for example, is the flag necessary?)? I’m concerned I’m missing something obvious because flags haven’t been covered in this course, and most FCC challenges require 1-2 lines to solve, not 10.

Your code so far


function filteredArray(arr, elem) {
  let newArr = [];
  // change code below this line    
  for (let i = 0; i < arr.length; i++) {
    let flag = true;
    for (let j = 0; j < arr[i].length; j++) {
        if (arr[i][j] == elem) {
          flag = false;
        }
    }
    if (flag) {
      newArr.push(arr[i]);
    }
  }
  // change code above this line
  return newArr;
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-data-structures/iterate-through-all-an-arrays-items-using-for-loops

Yes, you don’t need to use a flag, you can use continue the second you find elem in a subarray

Of course when filtering, filter is superior, but this is with loops on purpose

One thought:

Your test in the middle:

        if (arr[i][j] == elem) {
          flag = false;
        }

First of all === is a little faster than == (it doesn’t have to check multiple types). And if you find a matching element, I would break - there is no need to check the rest of the array. So I would have:

        if (arr[i][j] === elem) {
          flag = false;
          break
        }

That is a little faster.

Depending on how you define “efficient”. A nice functional solution is:

const filteredArray = (arr, elem) => arr.filter(a => !a.includes(elem))

Is it more “efficient”? It certainly looks smaller on the page. But ultimately those methods are just loops and probably it is going to be a hair slower because it has to make function calls.

But this is web development. If you want speed, then JS isn’t the best language. It’s good to think about these things, but for 98% or applications it won’t make a difference. Make some common sense efficiency decisions, be aware of the issues, but don’t obsess over it if it isn’t an issue. Sometimes the less efficient but more easily read, debugged, and maintained solution is better.

Yes, you don’t need to use a flag, you can use continue the second you find elem in a subarray

But then how does he know whether to push the array or not? This would probably work if you were looping inside a filter because you could just return false, but I don’t see how to make this work with nested loops. Maybe I need more coffee.

Sorry for the slow reply Kevin, I was travelling on the way home

You can use labels with continue just like how you’d use them in C-like languages with goto - it also works with break

As an alternative I guess it could be split with a subfunction and return could be used to the same effect? That may be more sane anyway, haha

Edit with MDN link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label

Yeah, I get that, but you still need logic as to whether or not to push the sub array or not. Yes, you could right a function and return a boolean, but at that point you’re basically doing your own filter function and getting away from the intent of the assignment. I think the intent of the assignment was nested for loops and I think you need a flag variable to tell you whether or not the subarray contained the element. Yes, you could continue to the outer loop, but then you would be skipping the logic deciding to push.

You push if you don’t find elem do you not? So if you don’t find elem you make it to the end of the loop and push, otherwise the continue takes you up a level and moves to the next array element

Honestly I would just do this with higher order functions anyway, but the task was to do it with nested loops

And for the record, I would avoid using labeled statements at all costs. They are very rare so they are going to catch a lot of people off guard and are essentially a goto statement which is usually viewed with skepticism in modern coding. There will almost always be a more traditional solution. And one that is using better coding practices.

OK, that makes sense. Yeah, that would work.

Yeah, I would use the Array methods (as the example I gave above). They are simple and clear. The only time I wouldn’t is if this were super efficiency critical - which it almost never is on a level that this would make a difference.

I agree with you there, and actually also in hindsight it’s likely less transparent to the js compiler and optimiser so may be way less efficient anyway!

Pretty much the only time I’ve used labels and gotos in C was cleanup within a function - though arguments about goto are older than I am, heh

So, here is the solution that gebulmer is suggesting:

function filteredArray(arr, elem) {
  let newArr = [];

  loop1:
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      if (arr[i][j] === elem) {
        continue loop1
      }
    }
    newArr.push(arr[i]);
  }
  return newArr;
}

It has a slight advantage over my nested loop solution that I offered in that it has one fewer variables. But I think it has the disadvantage of using an obscure JS trick that may catch people off guard and might be looked on as messy. He also says the compiler may have more trouble optimizing it - I’ll have to take his word for it because that is a little outside my ken.

We both agree that the functional approach is more common and almost always better - if it weren’t an assignment about for loops.

1 Like