Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript JavaScript Loops, Arrays and Objects Tracking Data Using Objects The Student Record Search Challenge

nico dev
nico dev
20,360 Points

Why doesn't 'continue' bring me through all iterations?

Hello community,

I am really puzzled with this challenge ('The Student Record Search Challenge' in the 'Js Loops, Arrays & Objects' course.)

While I am sure my code is still hugely imperfect (because of my lack of experience and because I am just new and learning), I don't want to give up and check the instructor solution BEFORE achieving more or less a decent result myself.

I have been working on this for some days (yeah, days already! :) and I solved many of the problems I faced, but now I find no way out of this particular issue: whereas in the following code I expect the 'continue' to go again to the 'for' and do the next iteration until either the 'if' or the 'else if' condition are fulfilled, for some reason it looks like the thing goes all the way up to the first 'do' and start prompting me again, before checking all the iterations. In other words: I never receive the 'Sorry, there's no student with that name. Try again.' message.

Please give me your valuable insight. What am I doing wrong in this specific code? What can I do better?

Thank you all in advance!

function print(message) {
  var outputDiv = document.getElementById('output');
  outputDiv.innerHTML = message;
  }

do {
  var nameRequest = prompt('Which student\'s data you\'d like to find out?');
    if ( nameRequest.toLowerCase() === 'quit') {
        break;
      } else {
          for ( var i = 0; i < students.length; i++ ) {
            if ( nameRequest.toLowerCase() === students[i].name.toLowerCase() ) {
              var message = '';
              var student = students[i];
              message += '<h2>Student: ' + student.name + '</h2>';
              message += '<p>Track: ' + student.track + '</p>';
              message += '<p>Points: ' + student.points + '</p>';
              message += '<p>Achievements: ' + student.achievements + '</p>';
              print(message);
              break;
              } else if ( i >= students.length ) {
                alert('Sorry, there\'s no student with that name. Try again.');
                break;
              } else {
                continue;
              }
          }
    }
} while ( nameRequest.toLowerCase() !== 'quit')

Ah, this is the main students.js file:

var students = [ 
  { 
   name: 'Dave',
    track: 'Front End Development',
    achievements: 158,
    points: 14730
  },
  {
    name: 'Jody',
    track: 'iOS Development with Swift',
    achievements: '175',
    points: '16375'
  },
  {
    name: 'Jordan',
    track: 'PHP Development',
    achievements: '55',
    points: '2025'
  },
  {
    name: 'John',
    track: 'Learn WordPress',
    achievements: '40',
    points: '1950'
  },
  {
    name: 'Trish',
    track: 'Rails Development',
    achievements: '5',
    points: '350'
  }
];

I doubt it's your problem, but you happen to be missing a semicolon on the end of your "quit" line. I'll attempt to look at this more closely in a few minutes, in case you haven't found a solution by then.

nico dev
nico dev
20,360 Points

Ouch. Thanks, Mike Wagner !

I will make sure to add it. Looking forward to your insight!

3 Answers

I'm a bit clumsy with JS myself, as I haven't had the time to actually focus on it, but it seems like you're not actually incrementing the i variable in your for loop if the name doesn't exist, at least, not in a way that's helpful to your loop structure. I'm not sure it's a perfect fix, but I fiddled around with it a bit, and it looks like if you change this section

print(message);
break;
} else if ( i >= students.length ) {
    alert('Sorry, there\'s no student with that name. Try again.');

a little bit to make it look like this

print(message + i);
break;
} else {  i++;  }

if ( i >= students.length ) {
    alert('Sorry, there\'s no student with that name. Try again. ' + i);

then it appears to achieve the result you want by forcing i to increment when a name isn't found during the for iteration. This may not be the way it's done in JavaScript, but it seems to work. I'll let you sort it out more, but this is a step in the right direction.

You can remove the + i concatenation on your alert/print calls, I added them to check what was going on. I left them in this code so that you could see for yourself how it responds. The printed/alerted i is equal to the index of the returned name(and its values) or 5(in the alert that the name was unfound), so it appears to be working. I'm no expert, though, so someone else might point out a flaw in my thought or show a more elegant solution.

Oh, and you don't need that final else { continue; } call, I'm pretty sure. Even with my "fix" your for/if functionality will basically only ever have a value between 0 and your array.length

nico dev
nico dev
20,360 Points

Thank you Mike Wagner, that was exactly what I was trying to do, to be honest :)

I just tried your solution and it works perfect. It is interesting, also, how adding the i (index) to the message variable, enables me to say in what position of the array that student is (perfect if you have a huge list with students numbered and you want the number of student, too).

I just came to some somehow similar solution myself (with the other also so valuable help and comments), but not even close to as neat as yours (because mine is checking the condition if i is lower than students.length minus one [a little weird isn't it?]). So I find yours much better + it has the interesting 'message + i' thing.

Big thanks for your insight!

Guess I feel ready to go on with the course and my conscience will be fine now :)

Nico Trivelli - Glad to be of assistance. I think you've pretty much got it under control, so just keep with it. All languages have their little quirks and everyone has their own way of doing things, but it seems like you're on the right track. I'm not even entirely sure that my solution is 100% effective, but it seemed to be moving closer to where you wanted to eventually get. Yeah, I always do little print/alert modifiers when I'm trying to sort out my own code, so I guess it was just habit. It was one of the first things I did when tinkering with your code. I did realize that I should probably take the JavaScript courses here to wrap my head around it better, though. It took me a bit to realize what it was even trying to do :)

You don't want to increment i inside the for loop since it's already being incremented in the for statement.

This would cause you to skip over students.

Jason Anello - I was thinking that too, but it seems that (in the original code) it wasn't actually holding onto i beyond the if-block, which is why even when the iterable hit the end of the array, it would skip over the else if ( i >= students.length ) entirely. I checked this solution against the included array and against 2 other arrays and achieved consistent results with my solution. Perhaps if the contents of the if statement were handled differently it would become a different story entirely. I couldn't answer that, as my knowledge with JS is fairly limited, but in my experiences in other languages, it's a relatively common scenario to approach by iterating within the if/else blocks when not using a raw for-loop. All I really know, is that by using my "solution," i returns the expected value and the for-loop functions the way it's expected. That's good enough for me unless someone can show a case where it wouldn't work.

Maybe I misunderstood where you're incrementing the i variable.

What happens if you do a search for the second student? Does it actually find that student?

Jason Anello - The way the code is set up is a little bit interesting, as it will continue to prompt for students after finding one or alerting to a student not being found, but yes. You can continue to type names in and it will find/not find as expected. When I tested the code in my solution I added a few alerts and modified the existing ones to return the student name, indices, and messages to make sure it was functioning as expected.

With the original code, as well as the solutions I could come up with which honored the for-loop's i value, for some reason, the code would not execute the structure of the else if-block properly. It would enter the else if and iterate up with the i as expected, however, the condition for i >= students.length was never met in a way that resulted in the "sorry" alert. I tried several block restructures and changes to the conditions, but when i became equal to 5 (in this case a "name not found" type of condition) it would just quit the else if and jump back to the prompt. Undoubtedly, my knowledge of JS is primitive at best, but I couldn't figure out an alternative that worked consistently other than this.

nico dev
nico dev
20,360 Points

Jason Anello sorry to jump back in. Yes, the way I see it (and with my extra-limited knowledge, I must clarify :) ) what Mike Wagner is doing, by adding 1 to the iterator (is that the name?) in the first else statement (an addition that will only work until the end of that iteration, because the next iteration will happen no matter what, except only for a 'break' statement) is done before the next if, in which he compares i with students.length (in other words: dear code, did you finish the whole for loop or there are yet more iterations to come?). Thank you for your question, because it made me not take the solution for granted and test it even farther.

I think that's actually the same I am doing by comparing, in an 'else if' statement, i with students.length minus 1, but of course, his way of doing it was (in my humble opinion) far more elegant than mine. Chapeau ! :)

And I am learning tones from you guys so please keep on doing this stuff in this community because it's really really helpful and teaching for newbies like me. I can't thank you all enough!

Let's see if we can trace through this.

To make sure I understand Mike's code, if the students name doesn't match then the else block will be executed and i will be incremented.

That's what I'll be assuming but correct me if I'm wrong.

Let's say "Jody" was typed at the prompt.

The first time through the loop, i will be 0 and there won't be a match on the name so the else will be executed and i will be incremented to 1.

The following if condition with the sorry message will be false and you will have reached the end of the loop. At which point i will be incremented again to 2 because you have that built into the for loop itself.

So when you reach the top of the loop for the next iteration, i will already be 2 and you will have skipped over "Jody" in the array. You'll be looking at "Jordan" instead.

I really don't see how "Jody" could be found if you're incrementing inside the loop because you're essentially doing a double increment each time.

Jason Anello - I actually agree with that logic, however, it didn't seem to present itself. Instead, it found any student that was expected to be found when asked to. There's something weird about that in my opinion, so I decided to tinker with the code again. I'll leave my original answer as a bit of a learning tool to display the odd behavior and in case someone can shed light on why it seemed to work and why it wouldn't. Here is my improved solution, though, I'm sure it can still become better:

// I have only displayed the for-loop, as that is the only thing
// that was changed from the original post's code. I removed
// my usual debug statements and alerts, save one, marked with
// a comment below. It seemed useful, so I left it implemented
// for now. I would probably leave it until project cleanup.

for (var i = 0; i <= students.length; i++) {       //  The main problem here resulted from the loop never actually reaching
  if (i < students.length) {                       //  students.length so by changint the for-loop to <= we can. This 
                                                   //  introduced indexing issues for the rest, so I encased it in an if-block.

    if (nameRequest.toLowerCase() === students[i].name.toLowerCase()) {
      var message = '';
      var student = students[i];
      message += '<h2>Student: ' + student.name + '</h2>';
      message += '<p>Track: ' + student.track + '</p>';
      message += '<p>Points: ' + student.points + '</p>';
      message += '<p>Achievements: ' + student.achievements + '</p>';
      print(message);
      alert("Student " + student.name + " found at index: " + i);        // This alert can be removed
      break;
    }
  } else if (i >= students.length) {
    alert('Sorry, there\'s no student with that name. Try again.');
    break;
  }                                                                     // The final else-block was removed as unneccessary
}

Nico Trivelli - I'm not sure if you're doing anything extra with the code, but it's worth noting that, once a student is found, the prompt is returned for a new name and it doesn't appear to update the HTML until you "cancel" or type in your "quit" name (which isn't displayed to the alert prompt *wiggles finger at you* naughty) to close the prompt. Behind the scenes, you will actually be able to just keep typing names into the prompt and it will continue to find them, one by one, regardless. That's a small reason why I decided to leave the alert saying the student was found in the above code. I'm pretty sure that if you used an input element on the page instead of an alert prompt that you would get instant feedback.

Anyway, like I said, this isn't a ~perfect~ solution (though it is better than my original answer), and I'm sure there are more efficient ways to do this, but I wouldn't be able to point you in that direction. It was interesting to toy around with and actually got me back into exploring JS a bit more, which is what I needed, so kudos to you for that. Good luck! :)

nico dev
nico dev
20,360 Points

Jason Anello , my apologies, I now see that you were right in one main aspect that I had misunderstood: that if the 'i' is incremented within the for loop, that increment will still be preserved for the next loop. I really thought that if that particular loop (let's say loop number 1) ended, then the for would increment 'i' from its value in the previous loop start regardless of what happened inside.

What I did now is I tried to search for Jody and John in particular (the odd indices) and the alert appeared saying there's no such student (when there are), so I made console.log(i) right after the start of the loop, to check what's the value of 'i' on each start of the loop, and it printed just 0, 2 and 4 to the console.

So, effectively, you're right in that aspect. Thank you for that's yet another (bonus) learning for me.

Mike Wagner , thank you for so much help! I tried your last solution, and this time I made sure even further, and it worked perfect in every case. Found it very clever how you create the for with i lower or equal than length because that sets the base for a perfect if/else if scenario, you have two options: either i is lower (i.e.: there are still more loops/students in the list) or i is equal (no more loops/students. Actually, tried removing the higher symbol in the else if and worked perfect, too, since 'i' won't reach there anyway).

Sorry if this is lengthy but I also want to answer what you said in last message.

it's worth noting that, once a student is found, the prompt is returned for a new name and it doesn't appear to update the HTML until you "cancel" or type in your "quit" name...

Yeah, fully agreed. The thing is that's exactly what the instructor requested. JavaScript seems to have had an important update after the video was published, and now it won't print until the end of execution. That was not like that when he made the video, the name was print as soon as you click 'OK', so you may either copy the data you want and search another name, or otherwise type quit and 'goodbye'. After this update, apparently, something a little bit different may be needed in real life, like a concatenation of all the names found, maybe creating an array and pushing all names that found a match, in addition to what's done here. I will probably try that myself later. But that's easy in comparison to what you helped me solve here. :)

Finally, really big thanks guys for so much help and teaching me! Can't thank enough!! I'll be back somewhere in this wonderful forum when I get stuck again. :)

You are calling continue inside a loop, yes, but it isn't called in the right loop. I've got stuck on this kind of thing numerous times, and it makes sense when you understand.

Let's just have a standard loop-inside-of-a-loop, or a nested loop. We want to continue on the outer loop, but want to use the continue keyword inside the inner loop. A first attempt might be this:

while (/*enter condition here*/) {
    while (/*enter condition here*/) {
        continue;
    }
}

This is just example code; it won't do anything if you actually run it.

When we call continue in the inner while loop, it doesn't do the continueing stuff on the outer loop. It calls it on the inner loop.

Your code:

// Stuff

do {
  var nameRequest = prompt('Which student\'s data you\'d like to find out?');
    if ( nameRequest.toLowerCase() === 'quit') {
        break;
      } else {
          for ( var i = 0; i < students.length; i++ ) {
            if ( nameRequest.toLowerCase() === students[i].name.toLowerCase() ) {
              // Stuff
              break;
            } else if ( i >= students.length ) {
                // Stuff
                break;
            } else {
              continue;
            }
        }
    }
} while ( nameRequest.toLowerCase() !== 'quit')

All the continues and breaks are called on the inner loop, which is not the effect you want. You want it to be called on the OUTER loop.

nico dev
nico dev
20,360 Points

Thank you Alexander Davison,

although (that's my fault, sorry on not commenting code properly) I want it to continue the inner loop. That is, within the for loop, if the name of 'i' matches the request print it and break. Otherwise, if it checked every iteration (and i is already equal to .length) then give me a message that the name was not found in the list, or if the i name did not match, but there are more iterations, then check the other iterations.

I am sure my code to achieve that is probably clumsy :) but I have really been trying and my problems have been multiple. I changed it a lot of times to solve each problem, but I remember that sometimes it would give me the message "There's not student" five times, which I suspected was because it was running the loop and giving me the message for each iteration. Then, I had the problem that it was giving the message even though the name was in the list, so I have been changing it a lot.

Not sure if I can find a way to receive the message now, avoiding all the other hassle that happened to me before :)

Maybe I should just re-propose the whole thing from scratch.

Thank you again for your help!

james south
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
james south
Front End Web Development Techdegree Graduate 33,258 Points

continue at the end of a loop doesn't do anything. by its nature the loop is going to loop again anyway. continue is for skipping code below the continue on some iterations (the loop will continue to the next iteration and will not execute what is after the continue). your else if is never going to happen because your loop variable i will never be greater than or equal to students.length.

nico dev
nico dev
20,360 Points

james south ... Food for thought. I see now what you mean, and that you're right. Working around it, as we talk, as best as I can.

Thanks!

nico dev
nico dev
20,360 Points

OK, I have now tried this one.

While I am sure there have to be better ways, at least it works. I based on the input of both of you Alexander and James. Do you have any further hint on how I could do it be better?

Once again, thank you for your huge patience and valuable insight!

function print(message) {
  var outputDiv = document.getElementById('output');
  outputDiv.innerHTML = message;
}

do {
    var nameRequest = prompt('Which student\'s data you\'d like to find out?');

      if ( nameRequest.toLowerCase() === 'quit') {
        break;
      }
      for ( var i = 0; i < students.length; i++ ) {
        var message = '';
        if ( nameRequest.toLowerCase() === students[i].name.toLowerCase() ) {
          var student = students[i];
          message += '<h2>Student: ' + student.name + '</h2>';
          message += '<p>Track: ' + student.track + '</p>';
          message += '<p>Points: ' + student.points + '</p>';
          message += '<p>Achievements: ' + student.achievements + '</p>';
          print(message);
          break;
        } else if ( i < (students.length - 1) ) {
          continue;
        } else {
        alert('Sorry, there\'s no student with that name. Try again.');
        }
      }
} while ( nameRequest.toLowerCase() !== 'quit');