Challenge 13 Filter


#1

Is it necessary to use the filter() method for challenge 13? I’ve coded something that I think should work without it, and I’m not sure if it’s a bug on my side or that the checkers explicitly looks for that.

function allCurrents(){
  var currentsArr = [];
  for(var i = 0; i < countRows(); i++){
    for(var j = 0; j < countColumns(); j++){
      if(isCurrent("ABCDEFGHIJ".charAt(j) + (i + 1).toString())){
        currentsArr.push("ABCDEFGHIJ".charAt(j) + (i + 1).toString());
      }
    }
  }
  return currentsArr;
}

Question about filtering Multidimensional Arrays (challenge 13)
#2

Although using ‘filter’ is not necessary (you can loop through all the elements as you do above), it is neat to explore and try to apply to today’s challenge :slight_smile:

Also, I pasted your code in an editor and it seems to have worked no problem. Try refreshing the online editor and re-submit your code.

Good luck!


#3

Yikes, that means I have a bug somewhere else… Time to get searching.

Thanks for your help!


#4

I did something very similar to this and it worked. @MMS, I noticed that your letter string assumes that the grid only has 10 columns; maybe Environment Canada has requested this report from all the lighthouse keepers, so we need to write a function that will work for a grid of any size (up to the max of 26)?

Or maybe you accidentally deleted a punctuation mark in one of your old functions while you were editing. Bugs are tricksy things.

I cannot figure out how to use filter in a way that doesn’t return an array full of rocks (or currents, or whatever we’re looking for). I’m going to keep noodling on that and maybe I’ll be able to grok it before end of day.


#5

I assumed it was the grid given, since it said “Environment Canada has called and wants a report sent to them of all the rocks and currents in your grid, for use in their latest map.” Currently looking for the bug, but it’s kinda difficult since I can’t test any of the previous challenges…


#6

I’m also having trouble figuring out how to use filter to get indexes instead of values, @RebelBeckerton . I’ve tried using indexOf in the return, but that doesn’t really make any sense because it still wants to build an array out of cell contents. I think I could figure this out using loops and pushing to an array, but I want to get practice using filter. Anyone have any tips/hints? I’ve done some reading and can’t find much on using filters for two-dimensional arrays, and it seems like nesting them won’t work with only getting contents from filter…


#7

Try reading this! https://medium.com/@joomiguelcunha/learn-map-filter-and-reduce-in-javascript-ea59009593c4


#8

Hmm I did read through it after looking at your other thread, but I’m afraid I must still be missing something obvious. Are you saying I need to use a combination of map, filter, and reduce? I’m currently attempting to map an array of just the coordinates in “A1” format, so I can compare the indices of that map to the original GRID, find the rocks, and return the filtered version of the map. Am I on the right track? If so, I’m having trouble figuring out how to map a 2D array…


#9

@MMS It is frustrating to not be able to test! If you don’t want to download software, there are browser tools that can help. Check out some of the suggestions in this topic:

Put in the code for const GRID and then plug in your functions one at a time. After each one do a console.log test. That should help you narrow it down? Good luck!


#10

Yep, I’ve done this, unfortunately I’m getting an expected output but it’s doesn’t work on the Lighthouse Labs site. Not really sure how to go from here…


#11

If you haven’t tried expanding it to work for all size grids as rebelbeckerton suggested then I would try that next.


#12

oh my gosh facepalm I forgot to try this with my updated code… I feel like such an idiot.

Thank you all for your help!


#13

Hey there, I personally don’t think filter is a good fit for this problem but I can see why it may seem like it. My reasoning is that it doesn’t give you exactly what you need. As an example for a given row you might have something like this:

["", "^", "~", "~", "", "", "", "^", "", ""]

and if you were looking for rocks "^" you may write a filter function like this

["", "^", "~", "~", "", "", "", "^", "", ""].filter((item) => {
    return item === "^"
})

which would output

[ '^', '^' ]

This result would filter (but not change, very important note!) the individual items of the previous array into a new array that contains only rocks. To further explain, this means that the new array would only contain items from the previous array (in other words, a subset). Going back to the challenge, this is not what we want. We want the coordinates of the rocks, so something like this:

['B1', 'H1'] 

Since those coordinates are nowhere to be found in the original array, it is not possible to perform a filter to get them out.


#14

I can confirm that you do not need a filter(). I want to challenge myself so I don’t read the hints unless I’m stuck, and I had this accepted as solved without getting stuck… But also without using a filter() :slight_smile:


#15

At first I also couldn’t see how the filter() method would be relevant to this challenge.

But after my non-filter solution failed to get accepted despite providing the correct output, I decided to play with the filter() method a bit more and came up with this.

I realized filter() becomes very useful if we first create an array with all the grid coordinates. Then we can combine filter() with functions we created in earlier challenges like isRock() and isCurrent(), and even countRows() and countColumns().

function columnOfIndex(columnIndex){
	return String.fromCharCode(65 + parseInt(columnIndex));
}

function allCoordinates(){
	let coordinates = [];

  for (let row=1; row<=countRows(); row++){
  	for (let columnIndex=0; columnIndex<countColumns(); columnIndex++){
    		coordinates.push(columnOfIndex(columnIndex) + row);
    }
  }
	return coordinates;
}

function allRocks(){
	return allCoordinates().filter(coordinate => {
  	return isRock(coordinate);
  });
}

function allCurrents(){
	return allCoordinates().filter(coordinate => {
  	return isCurrent(coordinate);
  });
}

Enjoy :grin:


#16

@Manveer Hey, I was wondering what would be the purpose of adding all the coordinates in your nest for loops? Have you considered just adding it conditionally. In addition, to make it reusuable i feel like you can just have allCoordinates() take in a parameter for what to look out like this allCoordinates(obstacle), then conditionally add the coordinates if it has that obstacle:

if (GRID[row][columnIndex] === obstacle){
    coordinates.push(columnOfIndex(columnIndex) +row);
}

This way, you’re not using up memory to fill out an x by y grid then filtering, and instead just adding what you need and return that.


#17

@MrCurvyCurves yup I tried adding coordinates conditionally. That was the first approach I tried. Unfortunately, Lighthouse Labs didn’t seem to like the array I created using the push() method :confused:

As per the original topic, I just gave an example here of how filter() can be practically put to use. Not saying it’s the best way. Though from the other methods I’ve seen and tried, it’s looking much better than I initially expected.


#18

@MrCurvyCurves adding an if statement to the nested loops could definitively work.

Just remember that for GRID, you need use use rowIndex not row.

let rowIndex = row-1;

if (GRID[rowIndex][columnIndex] === obstacle){
    coordinates.push(columnOfIndex(columnIndex) +row);
}

#20

you used row and not rowIndex so i was just referencing that


#21

I used row instead of rowIndex because I was using the loop to generate coordinates and not to read GRID items. So you’ll need to make that tweak if you want to use the loop in the way you described.


Having some trouble with 13