Array item iteration using for loop

I think my code works if you do not consider nested elements inside an array.

function filteredArray(arr, elem) {
   let newArr = [];
   for(var i = 0;i<arr.length;i++){
     if(arr[i]===elem){
       arr.splice(i,1);
       newArr = arr;
     }
  }
   return newArr;
 }

 console.log(filteredArray([1,2,3],3));

But when it comes to nested elements, how come this one does not work?

function filteredArray(arr, elem) {
  let newArr = [];
  for(var i = 0;i<arr.length;i++){
  	for(var j = 0;j<arr[j].length;j++){
    		if(arr[i]===elem||arr[i][j]===elem){
      		arr.splice(i,1);
      		newArr = arr;}
    }
  }
  return newArr;
}

console.log(filteredArray([1,[34],2],34));

wait… i think I fixed it:

function filteredArray(arr, elem) {
  let newArr = [];
  for(var i = 0;i<arr.length;i++){
  	for(var j = 0;j<arr.length;j++){
    		if(arr[i]===elem||arr[i][j]===elem){
      		arr.splice(i,1);
      		newArr = arr;}
    }
  }
  return newArr;
}

console.log(filteredArray([1,[34],2],34));

Is this related to a specific challenge? If so, could you link to it?

As it stands, I’m not sure what you want your code to accomplish.

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

The issue is that splice change the array.

So what happens is that you are changing the content of the array mid-looping, resulting in unexpected behaviour.

You should consider a different method that return a new array (or portion of it) without altering the original one, like slice


EDIT: a small hint.
you don’t really need a second loop to iterate in each array to find if elem is there.
indexOf can help you on that.
Maybe this can help you simplify the problem :slight_smile:

7 Likes

Marmiz is right that .splice() is part of the problem. (Though you probably could still get it to work with .splice() if your outer for loop works through the array backwards.)

Another issue might be your second for loop. It looks like you want to iterate through all the elements in each sub-array. In your initial post you had j < arr.length. In your later comment, you changed that to j < arr[j].length. But neither of those is what you want. Think again about how to write that second for loop correctly.

And as Marmiz also notes above, you don’t have to use a nested for loop. indexOf() is an option, as is .some(). That said, you might want to press on to see if you can figure it out, and then try the simpler solution later! Good luck!

1 Like

@michaelfoland

why this one works
29%20AM

but this one does not??

function filteredArray(arr, elem) {
  let newArr = [];
  for(var i = 0;i<arr.length;i++){
  	for(var j = 0;j<arr[i].length;j++){
    		if(arr[i]===elem||arr[i][j]===elem){
      		arr.splice(i,1);
      		newArr = arr;}
    }
  }
  return newArr;
}

console.log(filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18));

the only thing I changed is the console.log statement.

What’s the message you receive when you run that code in freecodecamp?

When the above is executed, arr’s length is now 2, so in the next iteration of the inner for loop (seen below), when i = 2, arr[2] no longer exists, because you spliced it out, so arr[2] evaluates to undefined and the error you receive “TypeError: Cannot read property ‘length’ of undefined” is what you get and the code stops executing. Two previous posters have given you insight in why your splice is causing you trouble. Try taking their advice and stick with slice, push the slice into newArr.

3 Likes

i will give it a try. thanks!

okay… I assume some kind of code belongs into the if statement… that involves indexOf(i)=!-1

I have no idea…
just gave me the answer.

function deleteElem(arr,elem){
	var newArr = [];
	for(var i = 0; i<arr.length; i++){
		if(){
			newArr = arr.slice(0,i);
			console.log(newArr);
		}
	}
	return newArr;
}
console.log(deleteElem([1,2,3,4,5],[5]));

@michaelfoland @RandellDawson

Is this code for a different challenge? The function name is different than the other code you posted.

nah its the same i just rewrote it

Instead of guessing a what code to put to pass the challenge, I strongly suggest you write out an algorithm which will satisfy the requirements of the challenge. Write it out in plain language and then walk through the test cases to see if you have all the correct steps. Post your algorithm here and we can help guide you on the code part.

In your unfinished if-statement here, you want to check whether arr[i] contains elem, right? Here are two ways to check that:

Maybe pick one of those and see if you can use it to identify which members of arr need to be pushed into newArr. Both of these methods are on the Array prototype, so they can be called on arr.

EDIT: Sorry, I should have said that some() and indexOf() can be called on arr as well as arr[i], so long as we can be sure that arr[i] is itself an array. In the challenge, I believe all members of arr are themselves arrays. But in some of your examples above, arr contains primitives as well as arrays.

1 Like

EDIT: removed explanation on why first works and second not since @RandellDawson did it already.
let’s avoid redundancy.

---- Now onto the challenge:

Let’s see if with some pseudo-code we can work this out - i’ll stick with your original idea instead of the alternative method we suggested, hoping to clarify some concept.

- loop into array
- expect each element to be an array with other element in it
- loop into nested array

- if nested array number is equal to 2nd argument 
we don't want this array to be in the return array

Let’s convert this:

function filteredArray(arr, elem) {
  let newArr = []; // we want to add into this.
  // for each entry into the array
  for(var i = 0; i<arr.length; i++){
  // now we look at each sub array
  var subArr = arr[i]; // reame so it's nicer to read
  // let's say that we don't know if elem is inside
  var isInside = false;
  	for(var j = 0; j< subArr.length; j++){
      if(subArr[j] === elem) {
        console.log("elem is in ", subArr)
        isInside = true
      }
    }
  console.log(subArr, ' contains ', elem, ' ? ', isInside)
  }
  return newArr;
}

filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18);

/*
[ 10, 8, 3 ] ' contains ' 18 ' ? ' false
[ 14, 6, 23 ] ' contains ' 18 ' ? ' false
elem is in  [ 3, 18, 6 ]
[ 3, 18, 6 ] ' contains ' 18 ' ? ' true
*/

There are tons of other approaches, this is, from my understanding what you had in mind.
Now you have to figure it out what you want to do once you know if isInside.

Hope this gives you a good start.
p.s. remember: don’t change the data while looping :slight_smile:

3 Likes

hello zhouxiang19910319 , first of all you have to make a loop , to iterate through all the nested arrays inside arr so what you should do is this :

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

for(let i=0;i<arr.length;i++){ // here arr.length=4 because the array we have contains for nested arrays.
if(arr[i].indexOf(elem)===-1){ // if arr[0] ===-1 ,means that the element is not existed so we push it
newArr.push(arr[i]); //here we push it and the loop works again untill the condtion is true
}
}
// change code above this line
return newArr;
}

I hope this helps

1 Like

Thanks, @Marmiz for your kind idea about using indexOf( ) to this challenge and I passed it with very minimal code. here is my solution:

function filteredArray(arr, elem) {
	let newArr = [];
	for(let i = 0; i < arr.length; i++) { //iterate all the item on arr
		if(arr[i].indexOf(elem) === -1) { // check if the required element have this arr or not
			newArr.push(arr[i]); // push the arr that doesn't contain the required element.
		}
	}
	return newArr; // return new array
}

// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3)); // output: [ ];
console.log(filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18)); // output: [ [10, 8, 3], [14, 6, 23] ]

Your feedback is really appreciated.

1 Like

you might want to add a spoiler tag to your solution.

:stuck_out_tongue:

1 Like

My solution was this:

Click to show code
    for (let i = 0; i < arr.length; i++) {
        let index = arr[i].indexOf(elem);
        index > -1 ? console.log(arr[i] + ' :: DEBUG Contains: 3') : newArr.push(arr[i]);
    }