Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

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

Student Record Challenge - How can I make my code shorter?

I have the code working how it is supposed to, but how can I make it shorter? I basically repeat myself for all five students, but I cant think of a way to turn that all into one conditional statement with a loop in it rather than five.

var stats = [
  {
    name: 'John',
    track: 'iOS Development with Swift',
    achievments: 5,
    points: 869
  },
  {
    name: 'Lansana',
    track: 'Front-End Development',
    achievments: 29,
    points: 2950
  },
  {
    name: 'Takodah',
    track: 'Web Design',
    achievments: 2,
    points: 314
  },
  {
    name: 'Bob',
    track: 'Android Development',
    achievments: 69,
    points: 1337
  },
  {
    name: 'Meg',
    track: 'Python',
    achievments: 3,
    points: 29
  }
];

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

var output = '';

do {
  var answer = prompt('Enter the name of a student [John] to search for their information. Enter "quit" to quit.');
  if (answer.toUpperCase() === 'JOHN') {
    for (var i = 0; i < stats.length;) {
      var student = stats[i];
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      break;
    }
  }
  if (answer.toUpperCase() === 'LANSANA') {
    for (var i = 1; i < stats.length;) {
      var student = stats[i];
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      break;
    }
  }
  if (answer.toUpperCase() === 'TAKODAH') {
    for (var i = 2; i < stats.length;) {
      var student = stats[i];
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      break;
    }
  }
  if (answer.toUpperCase() === 'BOB') {
    for (var i = 3; i < stats.length;) {
      var student = stats[i];
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      break;
    }
  }
  if (answer.toUpperCase() === 'MEG') {
    for (var i = 4; i < stats.length;) {
      var student = stats[i];
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      break;
    }
  }
} while (answer !== 'quit');

7 Answers

Hi Lansana,

This is what I came up with. I put the logic for searching into a function, keeping the code DRY.

Hope this helps,

Cheers

var stats = [
  {
    name: 'John',
    track: 'iOS Development with Swift',
    achievments: 5,
    points: 869
  },
  {
    name: 'Lansana',
    track: 'Front-End Development',
    achievments: 29,
    points: 2950
  },
  {
    name: 'Takodah',
    track: 'Web Design',
    achievments: 2,
    points: 314
  },
  {
    name: 'Bob',
    track: 'Android Development',
    achievments: 69,
    points: 1337
  },
  {
    name: 'Meg',
    track: 'Python',
    achievments: 3,
    points: 29
  }
];

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

function search(query) {
  var output = '';
  for (var index in stats) {
    student = stats[index];    
    query = query.toUpperCase();

    if (student.name.toUpperCase() === query) {
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      return;
    }
  }  
}

do {
  var answer = prompt('Enter the name of a student [John] to search for their information. Enter "quit" to quit.');
  search(answer);  
} while (answer[0].toLowerCase() !== "q");

Thank you.

Here is a different, and I think better, for loop to use.

function search(query) {
  var output = '';
  stats.forEach (function(student) {
    var name = student.name.toUpperCase();
    query = query.toUpperCase();

    if (name === query) {
      output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
      print(output);
      return;
    }
  });
}

Hmm.. I am actually trying to redo this right now but using the DRY method.

Here's one more way to write search() using filter, just to show another way.

function search(query) {
  var output = '';

  // filter() filters a given array, and returns a new array
  var students = stats.filter(function(student) {
    return student.name.toUpperCase() === query.toUpperCase();    
  });

  var student = students[0];

  output = 'Student: ' + student.name + '<br><br>' + 'Track: ' + student.track + '<br><br>' + 'Achievments: ' + student.achievments + '<br><br>' + 'Points: ' + student.points + '<br><br>';
  print(output);
}

Thank you! I have another question..

Why won't my indexOf code work? it in the else if statement:

If I take that else if out, the program runs fine. If I put it in and if I type "Lansana", it prints out the else if, and it shouldnt.

var studentScores = [
  { name: 'Lansana', exam1: 98, exam2: 97, exam3: 99 },
  { name: 'John', exam1: 90, exam2: 91, exam3: 94 },
  { name: 'Bernard', exam1: 90, exam2: 94, exam3: 96 },
  { name: 'Eddie', exam1: 86, exam2: 73, exam3: 88 },
  { name: 'Johnston', exam1: 72, exam2: 80, exam3: 37 },
  { name: 'Mary', exam1: 53, exam2: 90, exam3: 72 },
  { name: 'Sean', exam1: 78, exam2: 73, exam3: 87 },
  { name: 'Aaron', exam1: 84, exam2: 60, exam3: 76 },
  { name: 'Duke', exam1: 43, exam2: 50, exam3: 97 },
  { name: 'Morgan', exam1: 73, exam2: 80, exam3: 46 }
]

var output = '';
var search;
var student;

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

function getStudentReport(student) {
  var report = 'Student: ' + student.name + '<br><br>';
  report += 'Exam 1: ' + student.exam1 + '<br><br>';
  report += 'Exam 2: ' + student.exam2 + '<br><br>';
  report += 'Exam 3: ' + student.exam3 + '<br><br>';
  return report;
}

while (true) {
  search = prompt('Exam results - enter your name, or "quit" to quit:');
  if (search === null || search.toLowerCase() === 'quit') {
    break;
  }
  for (var i = 0; i < studentScores.length; i++) {
    student = studentScores[i];
    if (search === student.name) {
      output = getStudentReport(student);
      print(output);
    } else if (student.name.indexOf(search) === -1) {
      output = 'Sorry, that name is not in our system.';
      print(output);
    }
  }
}

The main addition is a break after a successful match.

while (true) {
  search = prompt('Exam results - enter your name, or "quit" to quit:');  
  if (search === "" || search.toLowerCase() === 'quit') {
    break;
  }
  for (var i = 0; i < studentScores.length; i++) {
    student = studentScores[i];
    if (search.toLowerCase() === student.name.toLowerCase()) {
      output = getStudentReport(student);
      print(output);
      break; // break once a match is found
    } else if (student.name.indexOf(search) === -1) {
      output = 'Sorry, that name is not in our system.';
      print(output);
    }
  }
}

Yes I recognize the break but my intentions with that code is that if you put anything other than the name of one of the students, then you will get the result in the if else statement. But that is not what happens. No matter what I enter, I get the result of the if else, even if I put the name of a student.

Hi Lansana,

Did you try the code I posted? The break statement fixes the problem you're describing.

Without it, the loop will iterate over all studentScores for every search - regardless of a match, so unless you type 'Morgan' as the student to search for (Morgan is the last student in the array), the output will always be 'Sorry, that name is not in our system.'

In addition to the break statement, I also lower-cased the comparisons making it more user friendly. For example, 'duke' will match 'Duke'. I also fixed the conditional that checks if the user wants to quit. If the user types nothing, search will contain the empty string instead of null.

Ahhh I see now what you did. I was out all day so I had thought that the break was in my original code also. I didn't realize that you added it into your response. Thanks.

And I have a question about toUpperCase and toLowerCase functions.. I just want to make sure I have this right.

Say, for instance, you have an array with a variable "Lansana" (capital L) in the index location of 0. If you made an if statement like this

if (answer.toUpperCase() === 'LANSANA') {

}

Then would it be a true statement if answer is Lansana, lansana, or any other combination of lowercase/uppercase letters spelling Lansana, right?

I don't know if I asked this correctly. I was under the impression that a variable.toUpperCase() === 'ALL CAPS' would give you the option to enter either lower case OR uppercase letters and still return true, but in the last JavaScript video in this course, he used toLowerCase which completely threw me off because I had been using that since the beginning.

Again, sorry for my poor wording but I don't know how else to ask.

Yep, you got it. We change the case to all upper or all lower to make it easier to test against some other value.

var answer = "eXaMpLe";

answer.toUpperCase() === "EXAMPLE" // true

answer.toLowerCase() === "example" // true

Thanks!