More universal and can work with any number of variables without changing much code

I found a way, which may not be simpler, but it is more universal and can work with any number of variables without changing much code:

2 Likes

Which can get tired when there are lots of values. In steps the rest parameter to bring order to a long argument list.

const finalGrade = (...grades) => {
  //  grades is now an array
}
console.log(finalGrade(50, 60, 70, 20, 45, 55, 75, 40))
51.875

Sorry, but I’m not sure I understand what you mean :thinking:

I’ve tried those numbers - it works fine :slightly_smiling_face:

The thing to read up on the rest parameter.

What does your code look like? Are you using all eight variables?

It took editing the code to manage more inputs. Rest parameters let us leave the code alone.

Got it. Yes, I’ve found the description at MDN, it really made the code cleaner. Thanks :+1: :slightly_smiling_face:

Yes, I did, but as you said, it took some editing the code.

Now it looks like this:

1 Like

Only thing to do now is handle exceptions, such as an empty arguments list.

  try {
    return grades.reduce((a, b) => a + b) / grades.length
  }
  catch (e) {
    return `${e}!`
  }
console.log(finalGrade())

TypeError: Reduce of empty array with no initial value!

What other types of errors do we need to catch?

1 Like

Or, I can switch the condition in the if statement and reduce the array only if it’s true :slight_smile:

Remember to include 100. This is still going to throw an error if the arguments list is empty. You could put the try..catch inside there and drop the avg variable (and the else clause).

 if ( ... ) {
   try {
     return ...
   }
   catch (e) {
     return ...
   }
 }
 return "You ..."

The jury might be out on this one, given the same outcome, either way. My way of thinking is to eliminate errant inputs before setting foot inside the working mechanism of the function. For that reason, I like the first version.

Below we include isNaN().

const finalGrade = (...grades) => {
  if (grades.some(grade => grade < 0 || 100 < grade || isNaN(grade))) {
    return "You have entered an invalid grade"
  }
  try {
    return grades.reduce((a, b) => a + b) / grades.length
  }
  catch (e) {
    return `${e}!`
  }
}
print (finalGrade(50, 60, 70, 20, 45, 55, 75, 40))
print (finalGrade(50, 60, 70, -20, 45))
print (finalGrade(50, 60, 70, 120, 45))
print (finalGrade(50, 60, 70, 20, 'a'))
print (finalGrade([50, 60, 70, 20]))
print (finalGrade())
print (finalGrade(50))

51.875
You have entered an invalid grade
You have entered an invalid grade
You have entered an invalid grade
You have entered an invalid grade
TypeError: Reduce of empty array with no initial value!
50

Yes, I totally forgot to include that and 0. Thanks :+1:

No, I don’t think it will. I’ve tested it with no arguments and NaN - it worked fine :slight_smile:

It’s just if you flip the if condition to:

if(grades.some(grade => grade >= 0 && grade <= 100) {
   avg = grades.reduce((sum, grade) => sum + grade) / grades.length;
}

and put the reduce function into it, then, if there are no arguments the condition of if won’t be fulfilled and it will go to the else, thus not throwing any error.

But of course, you can put reduce into try...catch, just to be safe :slightly_smiling_face:

The last thing we want to be is, glib. Until our code is bullet proof, it is vulnerable. Walking away is not an option. Code with vulnerabilities is not something we walk away from. Test it with all manner of illegal and errant values. Remember booleans could be treated as integers. Throw everything at it. Make it fail, and fix the broken code.

I’m most impressed when others break my code. It shows they are on the right track to being critical about code that others give them. Break MY code, if you don’t wish to break your own. Just break something.

3 Likes