Today’s coding session proved to be quite challenging. I found myself grappling with complex mathematical equations, which was particularly difficult for me since I tend to struggle with math, particularly word problems. I had to consult Google for assistance multiple times, but I did not make much progress. Unfortunately, it seems like I’ve taken a step back instead of moving forward.
I left my charging cable behind, but fortunately, my laptop had a full charge. Initially, I believed that my backpack contained an extra charging cable, but it turned out that the one inside was defective. Consequently, I’m left with only one functioning cable, which is currently connected to my desk.
Today, I find myself at the university library. Later on, Tommy and I have plans to catch a screening of Rascal Does Not Dream of a Knapsack Kid, the sequel to the beloved Rascal Does Not Dream of Bunny Girl Senpai. I thoroughly enjoyed the first movie, so I’m eagerly anticipating what the sequel has in store.
I had a relaxing weekend, mostly spent watching YouTube and playing Animal Crossing and Skyrim. While I enjoy Skyrim, it can sometimes be emotionally intense, so I’m taking my time with it. Having played the game multiple times, I’m familiar with the storyline.
I should have started placing some ephemera from my last Alaska trip in a notebook. I had the time to work on a travel journal. I’d also like to use photographs, so I will look into how to do that. I want to finish this before my next Alaska trip later this year. I collect a lot of ephemera; now I need to put it all together.
Yesterday was Alexis’s birthday, and it’s hard to believe she’s already 21. It feels like just yesterday, she was a child. As cliche as that sounds. However, in reality, it’s only been a short time since she entered adulthood. I feel nostalgic.
JavaScript notes…
————————————
Statistics calculator steps 1 – 35
Step 1
Statistics is a way of using math to make sense of data. It helps us understand patterns and trends in information, so we can make predictions and decisions based on that information.
In this challenge, you will build a statistics calculator that takes a set of numbers and returns the mean, median, mode, standard deviation, and variance.
The HTML and CSS have been provided for you. Feel free to explore the code – you may notice that the calculate function is called when the form is submitted. When you are ready, declare a calculate variable and assign it an empty function in the script.js file.
const calculate = () => { }
Step 2
To begin, the calculate function needs to find the number that was entered in the #numbers input field. To do this, use a .querySelector to locate the input field and then use the .value property to get the number entered.
Store this in a value variable.
const calculate = () => { const value = document.querySelector("#numbers").value }
Step 3
Now that you have the value of the input, you need to split it into an array of numbers. Use the .split() method to do this.
The .split() method takes a string and splits it into an array of strings. You can pass it a string of characters or a RegEx to use as a separator. For example, string.split(“,”) would split the string at each comma and return an array of strings.
Use the /,\s*/g regex to split the value string by commas. You can tweak it based on the number of spaces separating your values. Store the array in an array variable.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); }
Step 4
The value of an input element is always a string, even if the input type is number. You need to convert this array of strings into an array of numbers. To do this, you can use the .map() method.
Create a numbers variable and assign it the value of array.map(). Remember that .map() creates a new array, instead of mutating the original array.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(); }
Step 5
The .map() method takes a callback function as its first argument. This callback function takes a few arguments, but the first one is the current element being processed. Here is an example:
array.map(el => {
})
The callback function needs to return a value. In this case, you want to return the value of each element converted to a number. You can do this by using the Number() constructor, passing the element as an argument.
Add a callback function to your .map() method that converts each element to a number.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(el => Number(el)); }
Step 6
A user could put any text they want into the input box. You want to make sure that you are only working with numbers. The Number() constructor will return NaN (which stands for “not a number”) if the value passed to it cannot be converted to a number.
You need to filter these values out – thankfully, arrays have a method specifically for this. The .filter() method will allow you to filter elements out of an array, creating a new array in the process.
Declare a filtered variable and assign numbers.filter() to it.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(el => Number(el)); const filtered = numbers.filter(); }
Step 7
Much like the .map() method, the .filter() method takes a callback function. The callback function takes the current element as its first argument.
array.filter(el => {
})
The callback function needs to return a Boolean value, which indicates whether the element should be included in the new array. In this case, you want to return true if the element is not NaN (not a number).
However, you cannot check for equality here, because NaN is not equal to itself. Instead, you can use the isNaN() method, which returns true if the argument is NaN.
Add a callback function to your .filter() method that returns true if the element is not NaN.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(el => Number(el)); const filtered = numbers.filter(el => !isNaN(el)); }
Step 8
Array methods can often be chained together to perform multiple operations at once. As an example:
array.map().filter();
The .map() method is called on the array, and then the .filter() method is called on the result of the .map() method. This is called method chaining.
Following that example, remove your filtered variable, and chain your .filter() call to your .map() call above. Do not remove either of the callback functions.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(el => Number(el)).filter(el => !isNaN(el)); }
Step 9
That is as far as you can get with the calculate function for now. It is time to write your mean logic.
Create an empty function called getMean. It should take a single parameter array.
function getMean(array) { }
Step 10
The mean is the average value of all numbers in a list. The first step in calculating the mean is to take the sum of all numbers in the list. Arrays have another method, called .reduce(), which is perfect for this situation. The .reduce() method takes an array and applies a callback function to condense the array into a single value.
Declare a sum variable and assign array.reduce() to it.
const getMean = (array) => { const sum = array.reduce(); }
Step 11
Like the other methods, .reduce() takes a callback. This callback, however, takes at least two parameters. The first is the accumulator, and the second is the current element in the array. The return value for the callback becomes the value of the accumulator on the next iteration.
array.reduce((acc, el) => {
});
For your sum variable, pass a callback to .reduce() that takes the accumulator and the current element as parameters. The callback should return the sum of the accumulator and the current element.
const getMean = (array) => { const sum = array.reduce((acc, el) => acc + el); }
Step 12
The .reduce() method takes a second argument that is used as the initial value of the accumulator. Without a second argument, the .reduce() method uses the first element of the array as the accumulator, which can lead to unexpected results.
To be safe, it’s best to set an initial value. Here is an example of setting the initial value to an empty string:
array.reduce((acc, el) => acc + el.toLowerCase(), “”);
Set the initial value of the accumulator to 0.
const getMean = (array) => { const sum = array.reduce((acc, el) => acc + el, 0); }
Step 13
The next step in calculating the mean is to divide the sum of numbers by the count of numbers in the list.
Declare a mean variable and assign it the value of sum divided by the length of array.
const getMean = (array) => { const sum = array.reduce((acc, el) => acc + el, 0); const mean = sum / array.length; }
Step 14
Finally, you need to return the value of mean.
const getMean = (array) => { const sum = array.reduce((acc, el) => acc + el, 0); const mean = sum / array.length; return mean; }
Step 15
You can actually clean this logic up a bit. Using the implicit return of an arrow function, you can directly return the value of the .reduce() method divided by the length of the array, without having to assign any variables.
Update your getMean function as described above.
const getMean = (array) => array.reduce((acc, el) => acc + el, 0) / array.length;
Step 16
Now you need to use your new getMean function. In your calculate function, declare a mean variable and assign it the value of getMean(numbers).
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(el => Number(el)).filter(el => !isNaN(el)); const mean = getMean(numbers); }
Step 17
To display the value of mean, your app has a #mean element ready to go.
Use a .querySelector to find that element, and then set its .textContent to the value of mean.
const calculate = () => { const value = document.querySelector("#numbers").value; const array = value.split(/,\s*/g); const numbers = array.map(el => Number(el)).filter(el => !isNaN(el)); const mean = getMean(numbers); document.querySelector("#mean").textContent = mean
Step 18
If you test your form with a list of numbers, you should see the mean display on the page. However, this only works because freeCodeCamp’s iframe has special settings. Normally, when a form is submitted, the event triggers a page refresh.
To resolve this, add return false; after your calculate(); call in the onsubmit attribute.