1

This is my first post here. I'm new to Javascript and here's my problem:

I have four input fields in html. All the four input fields are not necessary to be filled by the user; one would be enough. Now my question is how to get the average of the inputs whether the user has given me only one filled field or 2 or 3 or even four of them filled.

Here's my starting code but there's a problem with it.

function calculateAll() {
    //first create an array to gather inputs from user and create the sum

    var listening_avg_array = new Array();
    listening_avg_array[0] = parseInt(listeningInput1_js.value);
    listening_avg_array[1] = parseInt(listeningInput2_js.value);
    listening_avg_array[2] = parseInt(listeningInput3_js.value);
    listening_avg_array[3] = parseInt(listeningInput4_js.value);

    //now we calculate the average for listening scores
    var sum = 0;
    for (var i = 0; i < listening_avg_array.length; i++) {
        sum += listening_avg_array[i];
    }

    var avg = sum / listening_avg_array.length;

    listening_avg_span_js.innerHTML = avg;
}

Unfortunately I get a "NaN" error if the user has given me only 3 or less inputs; But if the user gives me all the four inputs the code works, but it's only one of the possible conditions. Sometimes I may only get 2 fields from the user and I have to get the average by dividing the sum by 2.

I don't know how to do it.

And here's the html:

<input id="listening-input1" type="number" min="60" max="100">
<input id="listening-input2" type="number" min="60" max="100">
<input id="listening-input3" type="number" min="60" max="100">
<input id="listening-input4" type="number" min="60" max="100">
2
  • 2
    do you like to get the average only from filled fields? Commented Jul 7, 2018 at 11:35
  • @NinaScholz Exactly. Commented Jul 7, 2018 at 11:44

3 Answers 3

3

You could filter the inputs that contain NaN to get an array of set values:

const values = listening_avg_array.filter(value => !isNaN(value));

So then you can sum that up and divide it by its length:

const average = values.reduce((a, b) => a + b, 0) / values.length;

or if you prefer a good old for loop:

var sum = 0, count = 0;
for (const value of listening_avg_array) {
    if(!isNaN(value)) {
        sum += value;
        count++;
    }
}

const average = sum / count;
Sign up to request clarification or add additional context in comments.

1 Comment

Wouldn't that be wrong? (e.g. user entered 3 numbers, he'll calculate the avg by diving by 4)
1

You could omit the array and take the value directly after checking the value for an empty string or a NaN value. BTW, '' is not NaN, but a real value, which is not a number after converting.

function calculateAll() {
    var i, count = 0, sum = 0, temp;
    for (var i = 1; i <= 4; i++) {
        temp = document.getElementById('listening-input' + i).value;
        if (temp === '' || isNaN(temp)) continue;
        sum += +temp;
        count++;
    }
    document.getElementById('average').innerHTML = count ? sum / count : 'No values';
}
<input id="listening-input1" type="number" min="60" max="100" onchange="calculateAll()">
<input id="listening-input2" type="number" min="60" max="100" onchange="calculateAll()">
<input id="listening-input3" type="number" min="60" max="100" onchange="calculateAll()">
<input id="listening-input4" type="number" min="60" max="100" onchange="calculateAll()"><br>
Average: <span id="average"></span>

3 Comments

It did the job in the shortest way. Thanks.
Could you interpret this part of your code for me?: code innerHTML = count ? sum / count : 'No values';
sorry for the delay, it uses the conditional (ternary) operator ?: which has a check and returns either the first part or the second. it's like if for expressions.
0

If the inputs aren't treated individually somewhere else, using class instead of id is a better approach, and makes code short.

document.getElementById('calculate').addEventListener('click', function(e) {
  calculateAll();
});

function calculateAll() {
  let sum = 0, count = 0;
  const inputs = document.querySelectorAll('.listening-input');
  inputs.forEach(function(el) {
    if(!el.value) return;
    sum += parseInt(el.value);
    count++;
  });
  const avg = sum / count;
  console.log(avg);
}
<input class="listening-input" type="number" min="60" max="100">
<input class="listening-input" type="number" min="60" max="100">
<input class="listening-input" type="number" min="60" max="100">
<input class="listening-input" type="number" min="60" max="100">

<button id="calculate">calculate</button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.