Javascript Looping Array - javascript

I was trying to mess around javascript and I created a multidimensional kinda array:
var students = [ [['David'], [80]], [['Vinoth'], [77]], [['Goren'],[55]] ];
And then I created an if statements that will test if the student grade is F to A.
for (var i = 0; i < students.length; i++) {
for (var j = 1; j < students.length; j++) {
document.write(students[i][j] + "<br/>");
if (students[i][j] < 60) {
document.write(students[i][j] + " is Grade : F");
} else if (students[i][j] < 70) {
document.write(students[i][j] + " is Grade : D");
} else if (students[i][j] < 80) {
document.write(students[i][j] + " is Grade : C");
} else if (students[i][j] < 90) {
document.write(students[i][j] + " is Grade : B");
} else if (students[i][j] < 100) {
document.write(students[i][j] + " is Grade : A");
}
}
}
In my pursuit to output the name of the student and the grade I even end up creating three for loops which did not work.
I was wondering how can I achieve this output:
David's grade is 80 and is C Grade.
Vinoth's grade is 77 and is C Grade.
Goren's grade is 55 and is F Grade.
Any idea what's missing to my codes?

Other answers have suggested simplifying your array structure. If you really want to use your extra nesting, you need to do an extra level of indexing. But you don't need nested loops, because it's still just a linear structure.
for (var i = 0; i < students.length; i++) {
var student = students[i][0][0];
var score = students[i][1][0];
var grade;
if (score < 60) {
grade = "F";
} else if (score < 70) {
grade = "D";
} else if (score < 80) {
grade = "C";
} else if (score < 90) {
grade = "B";
} else if (score < 100) {
grade = "A";
}
document.write(student + "'s score is " + score + ' and is Grade ' + grade + '<br>');
}
Also, if you expect a score of 80 to generate a C grade rather than B, you should be using <= rather than < in the comparisons.
As a general rule, I recommend using objects rather than arrays for heterogeneous data, so your array should be like:
var students = [ {
name: 'David',
score: 80
}, {
name: 'Vinoth',
score: 77
}, {
name: 'Goren',
score: 55
}];
Then you use students[i].name and students[i].score, which is much easier to understand.
The idea is that you use arrays for collections of things that are all the same type, and objects for collections of related information about a thing.

Your data is structure is strange in that it is deeply nested.
I would transform it to the shallower:
var students = [ [ 'David', 80], ['Vinoth', 77], ['Goren', 55] ];
It would be better to define a single argument function for determining the grade letter:
function getGrade(value) {
if (value > 90) return 'A';
else if (value > 80) return 'B';
else if (value > 70) return 'C';
else if (value > 60) return 'D';
else return 'F'
}
I would prefer a forEach loop but since you seem to have a preference for the for, we can write:
for (let i = 0; i < students.length; i++) {
console.log(`${students[i][0]}'s grade is ${students[i][1]} and is a ${getGrade(students[i][1])} Grade`);
}

Your array is 3 level nested. So you might want to run 3 loops. However the second level has only 2 elements and the third level has only 1 element. So you can run only 1 loop. See the following working snippet.
var students = [ [['David'], [80]], [['Vinoth'], [77]], [['Goren'],[55]] ];
for (var i = 0; i < students.length; i++) {
document.write(students[i][0][0] + " ");
if (students[i][1][0] < 60) {
document.write(students[i][1][0] + " is Grade : F" + "<br/>");
} else if (students[i][1][0] < 70) {
document.write(students[i][1][0] + " is Grade : D"+ "<br/>");
} else if (students[i][1][0] < 80) {
document.write(students[i][1][0] + " is Grade : C"+ "<br/>");
} else if (students[i][1][0] < 90) {
document.write(students[i][1][0] + " is Grade : B"+ "<br/>");
} else if (students[i][1][0] < 100) {
document.write(students[i][1][0] + " is Grade : A"+ "<br/>");
}
}

If you really, REALLY want to just fix your solution with just the minimum modifications without touching your data, then you were missing 3 things to get the output you wanted:
document.write("<br>") at the end
inner loop until students.length - 1
name of stundent accessed as students[i][j - 1]
Here's the complete fixed code, run it by clicking "Run code snippet" at the bottom
var students = [ [['David'], [80]], [['Vinoth'], [77]], [['Goren'],[55]] ];
for (var i = 0; i < students.length; i++) {
for (var j = 1; j < students.length - 1; j++) {
document.write(students[i][j - 1] + "'s grade is ");
if (students[i][j] < 60) {
document.write(students[i][j] + " and is Grade : F");
} else if (students[i][j] < 70) {
document.write(students[i][j] + " and is Grade : D");
} else if (students[i][j] < 80) {
document.write(students[i][j] + " and is Grade : C");
} else if (students[i][j] < 90) {
document.write(students[i][j] + " and is Grade : B");
} else if (students[i][j] < 100) {
document.write(students[i][j] + " and is Grade : A");
}
}
document.write("<br>")
}

Your students array's inner elements such as name or grade are themselves wrapped in brackets and thus become arrays. Remove the inner brackets.
Also, your comparison operator < should become <= if you want a score of 80 to be rated as a 'C' as per your example.
let students = [['David', 80], ['Vinoth', 77], ['Goren', 55]];
// Define rating function:
let rate = (grade) => grade <= 60 ? 'F' : grade <= 70 ? 'D' : grade <= 80 ? 'C' : grade <= 90 ? 'B' : 'A';
// Map students to phrases:
let phrases = students.map((student) => `${student[0]}'s grade is ${student[1]} and is ${rate(student[1])} grade.`);
// Output DOM nodes:
phrases.forEach((phrase) => {
let el = document.createElement('div');
el.textContent = phrase;
document.body.appendChild(el);
});

Array of objects is a better data structure for this particular case. Plus I have separated the score to grade conversion to a function, which makes code easier to read and reason about.
function getGrade (score) {
var grades = [
{
letter: 'A',
minScore: 90
},
{
letter: 'B',
minScore: 80
},
{
letter: 'C',
minScore: 70
},
{
letter: 'D',
minScore: 60
},
{
letter: 'F',
minScore: 0
}
];
for (var i = 0; i < grades.length; i++) {
if (grades[i].minScore <= score) return grades[i].letter;
}
}
var students = [
{
name: 'David',
score: 80
},
{
name: 'Vinoth',
score: 77
},
{
name: 'Goren',
score: 55
}
];
students.forEach(function (student) {
var str = student.name +
"'s score is " +
student.score +
" and is " +
getGrade(student.score) +
" Grade.";
console.log(str);
});

I hope this will works for you
var students = [ [['David'], [80]], [['Vinoth'], [77]], [['Goren'],[55]] ];
for (var i = 0; i < students.length; i++) {
document.write("<br/>"+students[i][0] + "'s");
for (var j = 1; j < students.length; j++) {
console.log(students[i][0]);
if (students[i][j] < 60) {
document.write(students[i][j] + " is Grade : F");
}
else if (students[i][j] < 70) {
document.write(students[i][j] + " is Grade : D");
} else if (students[i][j] < 80) {
document.write(students[i][j] + " is Grade : C");
} else if (students[i][j] < 90) {
document.write(students[i][j] + " is Grade : B");
} else if (students[i][j] < 100) {
document.write(students[i][j] + " is Grade : A");
}
}
}

Related

Using a recursive function to find the factorial of a given integer

I'm trying to make a recursive function to print the factorial of a given integer. Ask the user to enter a positive integer and then display the output on a page. For example, if the user enters 5, the output must be
5 × 4 × 3 × 2 × 1 = 120
var integer = prompt("Enter a positive integer.");
function factorialize(num) {
if(num == 0 || num == 1) {
return 1;
}
else {
return num + " x " + factorialize(num-1) + num * factorialize(num-1);
}
}
document.write(factorialize(integer));
You can pass a runningTotal of the sum so far to each recursive call. You can also keep the solution compact using template literals.
function factorialize(n, runningTotal = 1) {
if (n === 1) return `1 = ${runningTotal}`;
return `${n} x ${factorialize(n - 1, runningTotal * n)}`;
}
console.log(factorialize(5));
You could handover the parts of product and result.
function factorialize(num, product = 1, result = '') {
return num === 0 || num === 1
? result + (result && ' x ') + num + ' -> ' + product
: factorialize(num - 1, product * num, result + (result && ' x ') + num);
}
console.log(factorialize(5));
console.log(factorialize(2));
console.log(factorialize(1));
console.log(factorialize(0));
I think make that recursively is quite confused:
function factorialize(n, expression = '', result = 0) {
if (n < 0) {
return null
} else if (n === 0) {
return (expression || n) + " = " + result
}
const newExpression = result ? expression + " x " + n : n
const newResult = !result ? n : result * n
return factorialize(n - 1, newExpression, newResult)
}
console.log(factorialize(5))
Is better to segregate the responsibilities:
function factorial(n) {
let fact = 1
if (n < 0) {
console.warn("Error");
return 0
} else {
for (let i = n; i > 0; i--) {
fact = fact * i;
}
}
return fact
}
function factorialExpression(n) {
let expression = ""
if (n < 0) {
console.warn("Error");
return ""
} else {
for (let i = n; i > 0; i--) {
expression += (i < n ? " x " : "") + i
}
}
return expression
}
function factorialize(n) {
if (n === 0 || n === 1) {
return n + " = " + n
} else if (n > 1) {
return factorialExpression(n) + " = " + factorial(n)
}
return null
}
console.log(factorialize(5))

Javascript: Average Grade and Letter Grade of Students

I was looking at this Javascript code to calculate the average grade of an array of students and then based on the result decide which letter grade should be assigned. I was wondering how would you display these two results in your HTML? I've played around and tried a few things but nothing seems to work. I'm also new to Javascript so the solution is most likely very simple but I'm just not sure how to go about it.
var students = [80, 77, 88, 95, 68];
var Avgmarks = 0;
for (var i = 0; i < students.length; i++) {
Avgmarks += students[i][1];
var avg = (Avgmarks / students.length);
}
console.log("Average grade: " + (Avgmarks) / students.length);
if (avg < 60) {
console.log("Grade : F");
} else if (avg < 70) {
console.log("Grade : D");
} else if (avg < 80) {
console.log("Grade : C");
} else if (avg < 90) {
console.log("Grade : B");
} else if (avg < 100) {
console.log("Grade : A");
}
EDIT: 09/10/2019
I have revised my code to this:
let students = [80, 77, 88, 95, 68];
let avgMarks = 0;
for (let i = 0; i < students.length; i++) {
avgMarks += students[i];
}
let avg = avgMarks / students.length;
if (avg <= 60) {
document.write("Grade : F");
}
else if (avg <= 70) {
document.write("Grade : D");
}
else if (avg <= 80) {
document.write("Grade : C");
}
else if (avg <= 90) {
document.write("Grade : B");
} else {
document.write("Grade : A");
}
document.getElementById("studentAvgGrade").innerHTML = avg;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Average Student Grade and Letter Grade</title>
</head>
<body>
<div id="studentAvgGrade"></div>
</body>
</html>
My code is now working. Thank you everyone for your help.
I would however like to know if this is the best way to go about solving the task using pure Javascript or is there a better way?
You can set the element with
const element = document.querySelector(YOUR HTML ELEMENT SELECTOR);
Then inside each if statement
element.innerText = grade
First declare a new variable for grade:
let grade = ""
then inside of your if/else statement variable grade gets assigned a new value with each condition.
in your html select the element where you would want it to appear and then assign variable grade as its innerhtml.:
<h1 id='grading'></h1>
and in your js:
let grade = ""
if (avg < 60){
console.log("Grade : F");
grade = "F"
}
else if (avg < 70) {
console.log("Grade : D");
grade = "D"
}
else if (avg < 80)
{
console.log("Grade : C");
grade = "C"
} else if (avg < 90) {
console.log("Grade : B");
grade = "B"
} else if (avg < 100) {
console.log("Grade : A");
grade = "A"
}
const gradeToDisplay = document.getElementById("grading")
grading.innerHTML = grade

How to iterate a value evenly and return the output it in one go

I'm trying to work a given set of parameters that define the minimum value and maximum value (minNumber, maxNumber). Basically, I want to take my minNumber, if it isn't even, find the nearest even number (if 5, use 6) and incremented it by 2 (6, 8, 10, ... maxNumber) until it is <= maxNumber. For example, if my minNumber = 4 and maxNumber = 21, my output = 4, 6, 8, 10, 12, 14, 16, 18, 20
This is my last attempt:
function evenNumbers(minNumber, maxNumber){
i = 0;
output = "" + minNumber + ", " + minNumber * i
if(minNumber % 2 == 0){
for (i = 2; i <= maxNumber; i+2){
output += ", " + minNumber * i
}
}
return output
}
Using this pre-defined set of parameters:
console.log('evenNumbers(4,13) returns: ' + evenNumbers(4, 13));
console.log('evenNumbers(3,10) returns: ' + evenNumbers(3, 10));
console.log('evenNumbers(8,21) returns: ' + evenNumbers(8, 21));
console.log('\n');
But now I'm getting an "out of memory" error. This is my desired output:
And just for the fun of it... here's a simpler version:
<script>
function evenNumbers2(minNumber, maxNumber){
var output = "";
for (var i = minNumber; i <= maxNumber; i++)
{
if (i % 2 == 0)
{
output += ", " + i;
}
}
return output.substring(2,999);
}
console.log('evenNumbers2(4,13) returns: ' + evenNumbers2(4, 13));
console.log('evenNumbers2(3,10) returns: ' + evenNumbers2(3, 10));
console.log('evenNumbers2(8,21) returns: ' + evenNumbers2(8, 21));
</script>
I think this is what you are looking for:
<script>
function evenNumbers(minNumber, maxNumber){
if(minNumber % 2 != 0){ minNumber++ }
var output = "" + minNumber ;
for (var i = minNumber + 2; i <= maxNumber; i = i + 2)
{
output += ", " + i;
}
return output
}
console.log('evenNumbers(4,13) returns: ' + evenNumbers(4, 13));
console.log('evenNumbers(3,10) returns: ' + evenNumbers(3, 10));
console.log('evenNumbers(8,21) returns: ' + evenNumbers(8, 21));
</script>
The function for getting the array of even numbers in the range
function even(a, b) {
var a = (a + 1) & 0xfffffffe;
var r = [];
for (; a <= b; a += 2) {
r.push(a);
}
return r;
}
This should be it:
function evenNumbers(minNumber, maxNumber){
var output = "";
if(minNumber % 2 != 0){
output = minNumber + 1;
for (i = minNumber+3; i <= maxNumber; i+=2){
output += ", " + i;
}
}
else{
output = minNumber;
for (i = minNumber+2; i <= maxNumber; i+=2){
output += ", " + i;
}
}
return output;
}
You forgot the "=" while updating the i value.
I also tried to clean up a bit the function.
Btw, if(x % 2 == 0) is true it means that x is even, if it is !=0 it is odd.
function evenNumbers(minNumber, maxNumber) {
# Check if even; add 1 to number if not
if (minNumber % 2 != 0) {
minNumber++
}
var arr = []
# Iterate through numbers, incrementing minNumber
# and creating array of output
while (minNumber <= maxNumber) {
arr.push(minNumber);
minNumber += 2;
}
# return array formatted as string with commas
return arr.join(',');
}

JavaScript: Numerical Grade to Letter Grade

1. Create a function toLetterGrade that takes an array of percentages and returns an array of corresponding grade letters. For example:
toLetterGrade([90,80,55,85]); //returns ["A","A-","C","A"]
2. Create a function toGradePoints that takes an array of letter grades and returns a corresponding array of grades points. For example:
toGradePoints(["A","A-","C","A"]); //returns [4.0,3.7,2.0,4.0]
3. Create a function GPA that takes an array of percentages and returns the corresponding grade point average.
I'm trying to do number 1, and this is the code I have so far, but it only gives me the letter grade for the last number in the array. What am I doing wrong?
var arr
function toLetterGrade(arr) {
for (i = 0; i < arr.length; i++) {
if (arr[i] >= 85) {
textG = "A";
} else if (arr[i] >= 80) {
textG = "A-";
} else if (arr[i] >= 75) {
textG = "B+";
} else if (arr[i] >= 70) {
textG = "B";
} else if (arr[i] >= 65) {
textG = "B-";
} else if (arr[i] >= 60) {
textG = "C+";
} else if (arr[i] >= 55) {
textG = "C";
} else if (arr[i] >= 50) {
textG = "D";
} else {
textG = "F";
}
}
return textG;
}
document.write(toLetterGrade([90, 80, 70]))
Output is B.
You are overwriting your variable with every cycle of the loop, that's why you are getting only one - the last grade.
I suggest you to use an empty array variable to store results inside.
With every loop you will assign new grade to the textG variable and then push it into the result array. The textG variable gets reseted with every loop textG = '' so there's no risk to duplicate/overwrite results.
After all cycles of the for loop, the result array is returned.
function toLetterGrade(arr) {
var textG = '';
var result = [];
for (i = 0; i < arr.length; i++) {
textG = '';
if (arr[i] >= 85) {
textG = "A";
} else if (arr[i] >= 80) {
textG = "A-";
} else if (arr[i] >= 75) {
textG = "B+";
} else if (arr[i] >= 70) {
textG = "B";
} else if (arr[i] >= 65) {
textG = "B-";
} else if (arr[i] >= 60) {
textG = "C+";
} else if (arr[i] >= 55) {
textG = "C";
} else if (arr[i] >= 50) {
textG = "D";
} else {
textG = "F";
}
result.push(textG);
}
return result;
}
document.write(toLetterGrade([90, 80, 70]))
For the first part, you could use an object and iterate the keys for the wanted grade.
function getGrade(p) {
var grade = 'F';
Object.keys(grades).some(function (k) {
if (p >= grades[k]) {
grade = k;
return true;
}
});
return grade
}
var grades = { A: 85, 'A-': 80, B: 70, 'B-': 65, 'C+': 60, C: 55, D: 50, F: '' }
console.log([90, 80, 55, 85].map(getGrade));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You're assigning the grade to a variable and then overwriting it with each iteration.
try textG.push('A') instead
You are overwriting your return value with each iteration.
Try creating an array, and adding the solution onto the array.
var solutionArr = [];
solutionArr.push("A");
jsfiddle
I make this simple code to check letter grade from a numerical
const letterGrade = (n) => {
let resultGrade = "";
if (n >= 90) {
resultGrade = "A";
} else if (n >= 80 || n > 89) {
resultGrade = "B";
} else if (n >= 70 || n > 79) {
resultGrade = "C";
} else if (n >= 60 || n > 69) {
resultGrade = "D";
} else if (n < 59) {
resultGrade = "E";
} else {
alert("Input your grade first");
}
return `Your grade is ${resultGrade}`;
};
console.log(letterGrade(75));

Want user to input number for for loop to run Javascript

Trying to have a user input a number and if they type in a string I would like to prompt them to enter a number. Seems like I got that part right but how can I get the second prompt to keep popping up until the user enters a an actual number. As of now, once the user enters a string again nothing runs after that. Would appreciate any kind of suggestions.
Here is the code:
function enterNumber(n) {
n = parseInt(prompt("Please enter a number: "));
if (isNaN(n)) {
n = parseInt(prompt("You did not enter a number. Please enter a number: "));
for(var i = 1; i <= n; i++) {
if (i % 15 === 0) {
document.write("Fizz Buzz" + "<br>");
continue;
}
else if (i % 3 === 0){
document.write("Fizz" + "<br>");
continue;
} else if (i % 5 === 0) {
document.write("Buzz" + "<br>");
continue;
}
document.write(i + "<br>");
}
}
};
enterNumber();
Use while loop until the entered is number.
function enterNumber(n) {
while (isNaN(parseInt(n))) {
n = parseInt(prompt("Please enter a number: "));
}
for (var i = 1; i <= n; i++) {
if (i % 15 === 0) {
document.write("Fizz Buzz" + "<br>");
continue;
} else if (i % 3 === 0) {
document.write("Fizz" + "<br>");
continue;
} else if (i % 5 === 0) {
document.write("Buzz" + "<br>");
continue;
}
document.write(i + "<br>");
}
};
enterNumber();
You can also shorten you code using nested Ternary operators as follow.
function enterNumber(n) {
while (isNaN(parseInt(n))) {
n = parseInt(prompt("Please enter a number: "));
}
for (var i = 1; i <= n; i++) {
var title = i % 15 === 0 ? 'Fizz Buzz' : i % 3 === 0 ? 'Fizz' : i % 5 === 0 ? 'Buzz' : i;
document.write(title + "<br>");
}
};
enterNumber();
Try like this
function enterNumber(n) {
while (isNaN(n))
n = parseInt(prompt("You did not enter a number. Please enter a number: "));
for (var i = 1; i <= n; i++) {
if (i % 15 === 0) {
document.write("Fizz Buzz" + "<br>");
continue;
} else if (i % 3 === 0) {
document.write("Fizz" + "<br>");
continue;
} else if (i % 5 === 0) {
document.write("Buzz" + "<br>");
continue;
}
document.write(i + "<br>");
}
};
enterNumber();

Categories