简体   繁体   中英

Issue with Javascript parallel arrays based on user prompt. How to stop going out of array bounds in loop?

I am having trouble with this problem. The program ask to take create a program which ask for a use input for the number of students and how many quiz they took that semester. The user should then be able to input the data into a parallel array.

So far, this is what I have.

 function getScores() { let studentNames = []; let studentScores = []; var arr = []; let input = ""; let nStudents = parseInt(prompt("How many students are there?")); for (i = 0; studentNames.length < nStudents; i++) { let name = prompt("Enter the students names"); studentNames.push(name); } let nTest = parseInt( prompt( "How many test did the " + studentNames.length + " student each take?" ) ); let temp = nTest * studentNames.length; for (i = 0; i < temp; i++) { while (i < temp) { let score = parseInt( prompt( "What was " + studentNames[i] + "'s Test " + " " + i + " score?" ) ); studentScores.push(score); i++; } } console.log(studentNames); console.log(studentScores); } getScores();

As you can see, There are mutlitple issues.

  1. My second loop will iterate over through the names, but once it gets to the last length of the array, it simply goes over into a new index and gets the value undefined. I tried to stop the loop when it reaches then end, but that is redundant being that I need to enter all of the test scores.
  2. Another issue is that I am iterating through the test in a way that iterates +1 after each new student. I don't want that. I would like each iteration of the loop to say "Test 1" for each student, and then move onto "Test 2" for each student again.

I am having trouble understanding where I am going about this wrong. I know that my loops are just not correct and there is most likely a much easier solution like 2d array, but I am trying to use parallels.

I am also wondering how these changes will come into play when I have to find the avg, lowest, and higher score for each user and print them to the screen. I usually find the sums but taking the sum of the whole array, but since I need to put all the score into 1 single array, I do not see how I will be able to dynamically grab the correct scores for each student and calculate them.

It seems like doing this with a parallel array would be VERY difficult, because than we don't know the number of test and students until the user prompt.

If there is an easier way to go about this, I am interested. I am not sure if I am even doing this parallel array method properly and I would love some insight from others, as I am still new to Javascript and arrays.

Use an object, not two arrays. I'm going to assume student names are unique (even though in real life they aren't, which is why we use student numbers), so have a single object studentScores and use that as your map:

const studentScores = {};

const N = parseInt(prompt("How many students are there?"));
for (let i=0; i < N; i++) {
  let name = prompt("Enter the students names");
  if (name) {
    studentScores[name] = 0;
  }
}

const T = get number of tests
Object.keys(studentScores).forEach(function(name) {
  for (let i=0; i<T; i++) {
    let score = parseFloat(prompt(`What did ${name} score on test ${i}?`));
    if (score) {
      studentScores[name] += score;
    }
  }
});

If you absolutely have to use parallel arrays, because you're trying to understand how you would use those, the basic concept is to never push into or pop from a single array. Your arrays are linked: if you push or unshift, you do that to both. If you pop or shift, you do that to both:

function getScores() {
  let input;

  const names = [],
    scores = [];

  // Get the number of students but VERIFY that you got a number:
  input = prompt("How many students are there?");
  const studentCount = parseInt(input);

  // There are many ways to verify this, but using JS coercion through ==
  // works quite well. This is one of the few times that == makes sense.
  if (studentCount == input) {
    for (let i = 0; i < studentCount; i++) {
      let name = prompt(`Please give the name for student number ${i}`);
      if (name) {
        // Here we GUARANTEE that the array positions for
        // this name and the associated score are the same:
        // if we push to `names`, we also push to `scores`,
        // so there is no possibility for the two getting
        // "out of sync" with respect to indexing
        names.push(name);
        scores.push(0);
      }
    }
  }

  input = prompt("How many tests did each student take?");
  const testCount = parseInt(input);

  if (testCount == input) {
    names.forEach(function(name, position) {
      for (let i = 0; i < testCount; i++) {
        input = prompt(`What did ${name} score for test ${i}?`);
        let score = parseFloat(input);
        if (score == input) {
          scores[position] += score;
        }
      }
    });
  }
}

Also note that I've corrected some things in your code: don't assume prompt gives you anything: it can be cancelled, and your code will break if you don't test for that. Also, parseInt or parseFloat give not you a number, they may give you a number, so test that they actually do before going into the code that relies on numbers.

Also, string composition: don't use string + string , use template literals and template in your values. Get into that habit now, it prevents a lot of string composition related bugs and headaches later, in other code.

Then, note that we're using for (let i=...) : this keeps i scoped to the for loop: it won't exist before it runs, and it won't exist after it's done. Unlike when you use for(i=...) , which is the same as for(var i=...) and actually makes i a function-scoped variable, meaning it already exists before the function code runs, and keeps existing after your loop's done. Which is almost never what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM