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 Solution

Patrick Mead
Patrick Mead
7,487 Points

Having weird problems with Part 1 solution and Part 2 solution conflicting. Any help is greatly appreciated!

I'm having such a weird problem with this one.

To do part 1, I put a break in the last IF statement behind the print getReport function in order to exit the loop. This worked fine when printing any name or the 'sorry' message when the name is wrong, but it interferes with how the code runs when printing names that show up twice, so I removed it.

For part 2, I moved the creation of the 'report' variable outside of the getReport function, so it would exist globally, and just created a line at the end of the while loop to clear out the 'report' variable with each time the loop ran the prompt. This is where it gets weird. It seemed to work just fine when printing the name that shows up twice in the array (Jared), but for some reason now if you type in any other name from the directly that shows up only once in the array, it defaults to the "sorry that is not a student" text which is created with the ELSE statement.

If I remove the ELSE statement at the very end, everything works perfectly, but then it won't use the 'sorry' text, which means part 1 doesn't work anymore. I just can't figure it out. Not sure if it's and problem with the if/else, the loop, how I set up my functions...Any help?

var students = [
  {
    name: 'Patrick',
    track: 'Javascript',
    achievements: 24,
    points: 1587
  },
  {
    name: 'Jon',
    track: 'CSS',
    achievements: 8,
    points: 956
  },
  {
    name: 'Mike',
    track: 'Ruby',
    achievements: 10,
    points: 1254
  },
  {
    name: 'Jared',
    track: 'HTML',
    achievements: 4,
    points: 687
  },
  {
    name: 'Jared',
    track: 'Python',
    achievements: 7,
    points: 894
  },
];


//Search engine

var message = '';
var student;
var search;
var report = '';

//Creates a function that converts array into a string
function getReport(student){
  for ( var i = 0; i < students.length; i+= 1 ){ //Loop through all students and update report
    report += '<h2>Name: ' + student.name + '</h2>';
    report += '<p>Track: ' + student.track + '</p>';
    report += '<p>Achievements: ' + student.achievements + '</p>';
    report += '<p>Points: ' + student.points + '</p>';
    return report; //Add data to report and return report
  } 
};

//Creates a function to print to ID output
function print(message){
  var outputDiv = document.getElementById('output');
  outputDiv.innerHTML = message;
};

//Prompts user for response
while (true) {
  search = prompt('Search for a student. Type "quit" to exit.');
  if (search === null || search.toLowerCase() === 'quit'){
    break;
  } //If 'quit" exit the function
  for ( var i = 0; i < students.length; i += 1 ) { //Loop through all students to check names
    student = students[i];
    if (search.toLowerCase() === student.name.toLowerCase()) { //If name is correct print getReport function
      print(getReport(student));

      // break; ---- If I add this just this break, the program will print either the name or 'sorry' message correctly, but won't be able to print multiple names
    } 
      // else {print('Sorry, that is not a student.');}  ---- If I add just this else statement, the program will work fine if you look for the person listed twice, but it displays the sorry message for any other name regardless of wether they are in the array

  } report = ''; //Refresh the report with each prompt
}

3 Answers

rydavim
rydavim
18,786 Points

Okay, so this part gets a bit tricky.

When using your code with both the break and the else code, everything works fine apart from not printing both records when you have the same name more than once. This is because you're printing the first student record you find, and then immediately exiting.

The easiest way to fix this is a bit lazy. You can remove the break and the else, use the global message variable you declared (which you're not using right now), and then add a check at the end to see if message is empty. There is probably a more elegant way to do this, but this would be my first thought.

var message = '';
var student;
var search;
var report = '';

function getReport(student){
  for (var i = 0; i < students.length; i+= 1) {
    report = '<h2>Name: ' + student.name + '</h2>'; // You'll need to generate a new report.
    report += '<p>Track: ' + student.track + '</p>';
    report += '<p>Achievements: ' + student.achievements + '</p>';
    report += '<p>Points: ' + student.points + '</p>';
    return report;
  }; 
};

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

while (true) {
  search = prompt('Search for a student. Type "quit" to exit.');

  if (search === null || search.toLowerCase() === 'quit'){
    break;
  };

  for (var i = 0; i < students.length; i += 1) {
    student = students[i];
    if (search.toLowerCase() === student.name.toLowerCase()) {
       message += getReport(student); // If there is a matching student, add it to the message.
    };
  }; 

  // This way you can print multiple students with the same name.
  if (message === '') {
    // If the message is empty, there was no student with a matching name.
    print('Sorry, that is not a student.');
  } else {
    print(message);
  };

  // Reset message instead of report.
  message = ''; 
};

Hopefully that helps give you an idea of what's going on. Try thinking of a way to make it more robust, elegant, and less lazy! Please let me know if you have any questions. Happy coding! :)

Patrick Mead
Patrick Mead
7,487 Points

Ok, I understand how your code works, but I still don't know why mine was behaving the way it was before. Let's say I take out that "break" at the end of my original code, but I keep the else statement that is currently commented out --- else {print('Sorry, that is not a student.'); --- I can't figure out why it will display the names of individuals that show up more than once in the list, but not the individuals who only show up once. If I type in "jared" (the only name that shows up twice), it prints everything just fine, but if I type in "mike" or any other name, it defaults to the else statement telling it to display the "sorry" text. That's the main part I can't figure out. It's not necessarily that I don't understand how yours works, but that I don't understand why mine didn't work and was behaving the way it was. Mainly I'd like to know so that if I have some misunderstanding about how the functions and statements are operating, I can address that in the future in case I run into another problem later because of a similar mistake. Thanks again for your help!

rydavim
rydavim
18,786 Points

Sorry for the delay, I didn't see your reply right away.

It's not that it works for names that show up twice. It only works for the last match(es) in the list.

for (var i = 0; i < students.length; i += 1) {
    student = students[i];
    if (search.toLowerCase() === student.name.toLowerCase()) {
       print(getReport(student));
       // If you don't have a break here, the loop is evaluating EVERY student. 
      // If you do have a break here, it will exit after the first match and not print the second student.
    } else {
      print('Sorry, that is not a student.');
      // Because there is no break, this will always be run last, unless you searched for the last name in the list.
    };
  }; 

So even if you find a match, the match is over-written by the later non-match unless you search for the last match(es) occurring in the list (which happens to be the name that appears twice). I believe that's what's happening.

Hopefully that clears things up a bit, but please let me know if you have any other questions. :)

Patrick Mead
Patrick Mead
7,487 Points

Ooh ok, that makes a little more sense. I still can't say I fully grasp why it will only print the last name on the list though. If you leave out the break, and the loop does in fact evaluate every student, why does it only print it if you searched the last one? In other words, why is it that the match is over-written by the non-match unless you're searching for the last student on the list? What is the significance of it being the last item on the list?

Also, if you search for another name that is in fact on the list (though not the last name), how is it that it's overwritten at all? Maybe I'm confused about how if-else statements work, but if the "if" condition is met (which it should be if you type in any name from the list), why is it even running the "else" statement at all? I wasn't even sure why I'd need the break at all; I just tried it thinking it might work (which it sorta did, though it wouldn't work with printing multiple names), though I'm not sure why the break would even be necessary to exit the if-else statement. Thanks again for all your help. I'm sure eventually this will all sink in, and I'll understand what's going on.

rydavim
rydavim
18,786 Points

Okay, let's add some code so you can see what's happening as the program runs. Try using the following code I've modified from your original version. This does not include a break, and does have the else clause.

// For EACH (every) student in the list, do the following...
for (var i=0; i < students.length; i++) {
  student = students[i];
  if (search.toLowerCase() === student.name.toLowerCase()) {
    print(getReport(student));
    console.log("This is iteration number " + i + " and you found student: " + student);
  } else {
    print("Sorry, that is not a student.");
    console.log("This is iteration number " + i + " and you didn't find a student.");
  };
};

Then use the developer tools in your browser to take a look at the console as the program runs. Keep in mind that if the print function is called anytime after you printed getReport(student), then it will be overwritten with the else phrase.

I hope that being able to watch what's happening inside your for block will help make things clearer, but please let me know if you have any other lingering questions. It's great that you want to understand the way these blocks work thoroughly. :)