Posted in freecodecamp, tutorial, web dev

Learn Functional Programming by Building a Spreadsheet

freecodecamp.com tutorial

**This is not meant to be a tutorial or a guide on how to complete the tutorial. This is just my thought process and notes as I go through the steps myself.**

Very interested in this one because I think it’ll help with some of the ideas I have for the future (like accounting adjacent stuff). Going to try to keep it brief this time, maybe only touch on the steps that I have to think about.

First step is to generate cells for the spreadsheet. I will use the window object to create containers (divs) when the page loads with the onload property. There is already a div in the HTML with the ID of “container.”

window.onload = () => {
  const container = document.getElementById("container")
}

Nested functions are great for when a function needs to reuse logic. I will use a nested function inside of the above one to create new div elements on the page.

Inside of the nested function I will also assign a class name to the new div by using .className and change the .textContent of the new divs to be the value of the name parameter. Lastly, the div will be appended to the container element (which is a different div). Because all of this is inside the .onload event, it will happen as soon as the page loads.

window.onload = () => {
  const container = document.getElementById("container");
  const createLabel = (name) => {
    const label = document.createElement("div");
    label.className = "label";
    label.textContent = name;
    container.appendChild(label);
  }
}

Next I need a function to generate a range of numbers (called range). I will do this using start and end as parameters, and the Array() constructor to return an empty array. The .fill() method is used to fill the array with the start value. Then the .map() method is used to iterate over the array and transform each element in the array according to the given function. In this instance I will be using element and index as parameters, and add them together to get the new element value to put in the array.

const range = (start, end) => Array(end - start + 1).fill(start).map((element, index) => element + index);

This same function pattern can be used to create a range of letters. The start and end parameters in this function, however, will be letters. (I am thinking this is going to be the letters going down the side to designate the cells. It would have been nice if they explained what we were doing before telling us to do it).

To do this, the .charCodeAt() method is used. This method returns a Unicode number that should correspond with the letter that is needed. A 0 is used as the argument. This will be added to both start and end.

As before, range() will return an array of numbers, which will need to be converted back into characters. The .map() method can help with this. It will be chained to the range() function call and have a callback function with String.fromCharCode() in the body. This method returns a string from a sequence of Unicode (UTF-16) values.

After that, I assign the charRange() function to the the variable letters with the letters A and J as arguments. This causes the browser to display the letters A – J across the top of the page with the addition of some pre-written CSS.

Calling letters.forEach(createLabel) will call the function createLabel() that is nested inside of the window.onload event. This nested function is the one that creates the divs for the document. The range() function returns an array, so array methods can be chained to it. Then we do a similar process for the numbers that would typically be found across the left-hand side of a spreadsheet.

The next step was asking to create an input element and set the type and ID. Creating the element was easy, but I was unsure of the syntax for adding the type and ID. I tried input.type(“text”) and that wasn’t correct (at least according to the exercise, maybe it is an alternative way to do it, unsure at this point). I also tried input.setAttribute(“text”) which didn’t work (also unsure if this is an alternative correct way to do it). I tried setAttribute() for ID as well but it didn’t work that way. The exercise wanted the following:

    letters.forEach(letter => {
      const input = document.createElement("input");
      input.type = "text";
      input.id = letter + number;
    })

The next step explains the syntax that the previous step wanted so I’m wondering if they edited the steps and should have put some of the instruction that’s in 18 on step 17. All they’re asking in 18 is to set the aria label (very important for screen readers), and then after they ask to append the input element as a child to the container div.

Working on built in functions for the spreadsheet to add numbers together etc. Must remember that .reduce() requires a callback function with two parameters, and ideally a starting number (at the end).

const sum = (nums) => nums.reduce((nums, currentValue) => nums + currentValue, 0);

Next I will use the sum() function in the newly created average() function to find the average of the array:

const average = (nums) => sum(nums) / nums.length;

I had a bit of trouble with .slice() and .sort() again.

onst median = (nums) => {
  const sorted = (nums) => nums.slice().sort((a,b) => a - b)
}

I had an extra arrow function that wasn’t needed.
This is the correct way to do it:

const median = (nums) => {
  const sorted = nums.slice().sort((a,b) => a - b)
}

The next part I need to use a Ternary to check if the length of the array is even or not. I always think Ternary operators are cool, not sure why. Maybe it’s the simplicity. Anyway, this is another one I was having trouble with. There are a lot of variables that need to be passed into the correct areas and since I still don’t have a full grasp on referencing indexes in arrays, I think that’s why it was a bit confusing for me.

Normally this would all be written on one line but I wanted to explain the parts and it was easier to do on different lines.

return isEven(length)     // this calls the isEven() function and passes the variable length as the argument
? average(sorted[middle], sorted[middle +1]     // this one calls the average() function and passes in the sorted array with the index calculated with the *middle* variable if isEven(length) returns true
: sorted[Math.ceil(middle)]     // the last part takes the value from the *middle* variable of the sorted array and rounds it up using Math.ceil.

All on one line it would be:

return isEven(length) ? average([sorted[middle], sorted[middle +1]]) : sorted[Math.ceil(middle)]

I was going to try to just do one tutorial per post from now on, but I’m having a not so great mental health day so I think I’m going to stop for now. Hopefully tomorrow is better.

Posted in freecodecamp, web dev

Roman Numeral Converter

I was able to get 1-19 working. I stopped to think about the best way to go about 20+ with keeping the code as short as possible… instead of doing a function for every 10 numbers (20-29, 30-39 etc). I was trying to accomplish this with for loops but haven’t gotten very far just yet.

I took a bit of a break to work on more tutorials and think about this one some more, but I’m still kind of stuck so I guess the best way to figure it out will be to work on it instead of just think about it.

I was going to try using an object and keys instead of a bunch of if/else statements, but I’m not quite sure how that would work. I started off by making an object of Roman Numerals based on a chart (this one specifically).

Roman Numerals Chart showing the Roman Numeral equivalent of numbers 1 - 1001

As a refresher, a new object is created by assigning a pair of curly brackets to a variable. Inside those brackets are key/value pairs written in the format key: “value” and separated by a comma. There can be more to it but this will do for my purposes.

To access the properties, dot notation is used, similar to using methods and such. There is also bracket notation, but it seems to me that dot notation is used more. However, if a property name is not a valid JS identifier (like one that has a space or hyphen), bracket notation would have to be used.

So with dot notation it would look like myObject.key = “value”.
With bracket notation it would look like myObject[“key”] = “value”

The more I think about it I’m kind of wondering if using objects will really make things more compact. I’m still going to need to do if statements to check the user input. Maybe just going with what I was doing is better for now, because at least I can finish the project even if it isn’t the most compact/efficient code. I’ll also get plenty of practice with functions and if statements.

What I had started doing was checking if the input was less than or equal to certain digits and then modifying the inner text with the correct roman numerals. This is going to cause a lot of repeated code patterns unfortunately.

Another thing I just realized/remembered was that some of the if statements needed to have parseInt() in them, whereas others didn’t. This is because of JavaScript’s type coercion and the different comparison operators.

Since === is a strict equality operator, no coercion is done and the user input need to be converted to a number type so that the values can be compared.

The comparison operators <= and >= are not strict so JS can try to force the type to match.

I was trying to create a parsed version of the variable so I could just put that in the conditions, but for some reason that didn’t seem to work even though I think it should. It’s another one of those things where it would be nice to have someone to talk to about how it works/doesn’t work but alas, I don’t have anyone.

Ok I had another idea. Maybe I can make a variable to use for the first digit, then I can just else if the ones place. Perhaps something like numberValue.value[0]? That didn’t work though so maybe I’ll revisit the idea later.

I went ahead and did the 20s. I really don’t like that I’m repeating so much but I also am at a loss for how to do it better.

Posted in freecodecamp, tutorial, web dev

Learn Advanced Array Methods – Part 4

Building a Statistics Calculator (Step 28 – 58)

Freecodecamp.com Tutorial

**This is not meant to be a tutorial or a guide on how to complete the tutorial. This is just my thought process and notes as I go through the steps myself.**

Now I am on the part where we need to find the mode. The mode is the number that appears most in the list. I start out by declaring a function named getMode which takes array as a parameter like before. Inside of the function I need to loop over the elements in the array and count the occurrence of each one to find which occurs most often.

Probably the easiest way to do this is to use a forEach() loop and to store the results in an object where the key is the number and the value is the amount of times the number appears in the set.

In the forEach() loop, the goal is to increment the counts[el] by 1 each time the object is found. If it is not found, counts[el] is reset to 1.

So what I have so far:

const counts = {}; // assigning an empty object to counts
array.forEach(el => {  // initiating the forEach loop
if (counts[el]) {  // checking if counts[el] is truthy
counts[el] += 1;  // adds 1 to the value of counts[el]
} else { 
counts[el] = 1; // sets the count back to 1
}
})
return counts;  // returns the counts variable;
}

If every value appears the same number of times, there is no mode. To test for this we can use a Set(). A Set() is a data structure that only allows unique values. It will remove duplicates if an array is passed into it.

What I need to do next is create an if statement that checks if the size property is equal to 1, which would indicate that every value appears the same number of times. So I create a new Set() in the condition of the if statement. The Set to be evaluated are the values in the counts object (Object.values(counts)). Then dot notation is use to add the .size property to the set.

  if (new Set(Object.values(counts)).size === 1) {
    return null;
  }

Took me a few tries on this because I don’t remember accessing an object in this way before so I wasn’t sure of the proper syntax. I had to look that up but it wasn’t difficult to find.

After this if statement is done, I need to figure out what value occurs with the highest frequency using the Object.keys() method and then .sort() it. The instructions say to use the count object to compare the values of each.

Object.keys() is used to get an array of the keys out of an object. They didn’t really explain that in the exercise. Anyway here’s the finished code for the mode.

const getMode = (array) => {
  const counts = {};
  array.forEach((el) => {
    counts[el] = (counts[el] || 0) + 1;
  })
  if (new Set(Object.values(counts)).size === 1) {
    return null;
  }
  const highest = Object.keys(counts).sort(
    (a, b) => counts[b] - counts[a]
  )[0];
  const mode = Object.keys(counts).filter(
    (el) => counts[el] === counts[highest]
  );
  return mode.join(", ");
}

The next thing that needs to be done is the function to get the range, which is the difference between the largest and smallest numbers in the list.

Before, Math.floor() was used to round a number down to the nearest integer. There are many Math methods built into JavaScript. Two more are .min() to get the smallest number, and .max() to get the largest. Using those Math methods we can pull the largest and smallest numbers, then subtract them to get the range. This one is very simple.

const getRange = (array) => {
  return Math.max(...array) - Math.min(...array);
}

Variance is the next one. It represents how much of the data deviates from the mean. I’ve never done this before (like in school) so this is new to me. It will take a few steps. The function will first get the mean from the getMean() function, then use array.map() to subtract the element from the mean. After that we square each of the differences using ** 2, then find the sum of the squared differences. To find the sum of the squared differences, .reduce() can be used. Don’t forget to add the initial value of the accumulator in the code!

Apparently all of that can be put into the reduce call to make the code less messy. After that is all condensed, the last thing to do is divide .reduce() by the length of the array in the variance declaration, then return variance.

Finally, the last calculation is standard deviation which I have also never heard of before but oh well. Evidentially it is the square root of the variance which shouldn’t be too difficult to pull off. I start by assigning a call to the getVariance() function inside of the new getStandardDeviation() function. Another Math method, .sqrt() is used to find the square root of a number. Who would have known. That can be used on the variance variable that I declared in the getStandardDeviation(). Then I update the HTML to show the result and the Statistics Calculator is completed.

Thoughts:

(On Blogging)

Trying to complete these tutorials while writing about them has been taking exponentially longer than just doing the exercises. My goal is to finish this one up today, then I can go back to working on my Roman Numeral Converter project, which is not a tutorial and is far more interesting than just writing about what I’m told to do. I will have to reevaluate how I do this because it is not sustainable long term. I suppose I could just write about the things that I have trouble with, instead of covering the entirety of the exercise.

Posted in web dev, freecodecamp, tutorial

Learn Advanced Array Methods – Part 3

Building a Statistics Calculator (Step 21 – 27)

Freecodecamp.com Tutorial

**This is not meant to be a tutorial or a guide on how to complete the tutorial. This is just my thought process and notes as I go through the steps myself.**

As a reminder, I am working to find the median of the array next. I’m going to be using the modulus operator to check if the array’s length is even or odd. This is a simple expression that divides the number I want to check (in this instance, the length of the array) by 2. If there is a remainder, it is an odd number. If not, it is even. To clarify, modulus divides the numbers, but it returns the remainder, not the result of the division. So you’re just checking for 0 or 1. Examples:

// check if array length is even
arr.length % 2 === 0;

// check if array length is odd
arr.length % 2 === 1;

In the project I’m building, I’m going to create an isEven variable that uses modulus to check if the length is an even or odd amount, and obviously I will use the expressions shown above. Evaluating the expression will return true or false.

To get the middle number of an array with an odd amount of elements, I will need to do a few things. First we need to get the number of elements of the array by using testArr1.length.

Once the length of the array is known, the next step is to divide it by 2 to get to the middle. A length with an odd amount of elements will return a decimal number, so Math.floor() will need to be used to change that decimal to the nearest integer less than or equal to it.

Finally, all of that needs to be wrapped in testArr1[] so that the index in the middle of the array will be returned, allowing the value of the element to be accessed.

testArr1[Math.floor(testArr1.length / 2)];

A similar method is used when the length of the array is an even amount, however the two numbers in the middle need to be accessed, not just one.

testArr2[(testArr1.length / 2)];
testArr2[(testArr1.length / 2) - 1];

Once the two middle values are gathered, the mean of the two numbers must be found to get the median. For this, the function we already have to get the mean for the first part of the calculator can be called. That way code isn’t rewritten and it keeps everything cleaner.

const evenListMedian = getMean([testArr2[testArr2.length /2], testArr2[(testArr2.length / 2) - 1]])

On this next step it is asking me to apply what I learned on the previous step to the actual function (before it was just practice). I thought I did that but it is still telling me it isn’t correct. Now I get to figure out why..

const getMedian = (array) => {
  const sorted = array.sort((a, b) => a - b);
  if (sorted.length / 2 === 0) {
    return getMean([sorted[sorted.length / 2 - 1], sorted[sorted.length / 2]]);  
  }
}

First error I think was that I used / 2 instead of % 2 in the if condition so I fixed that.

Oh, I forgot to put the code for if the length is odd. Oops.

const getMedian = (array) => {
  const sorted = array.slice().sort((a, b) => a - b);
  const median =
    array.length % 2 === 0
      ? getMean([sorted[array.length / 2], sorted[array.length / 2 - 1]])
      : sorted[Math.floor(array.length / 2)];
  return median;
}

There we go, fixed. I also added .slice() before .sort() to create a ‘shallow copy’ of the array so we don’t mutate the original. Then we just need to update the text content of the #median element and that part is all finished.

Posted in web dev, freecodecamp, tutorial

Learn Advanced Array Methods – Part 2

Building a Statistics Calculator (Step 10-21)

Freecodecamp.com Tutorial

**This is not meant to be a tutorial or a guide on how to complete the tutorial. This is just my thought process and notes as I go through the steps myself.**

For the next segment, I start by creating a new function that I will use to find the mean of the series of user input numbers. It takes our array variable as the parameter. To find the mean (as I’m sure most people know) you need to add all of the numbers of the series and then divide the total by how many numbers there were. So if you had 10 numbers you would add them together and divide the total by 10.

To do this, I can use the array method .reduce(). This is a method that uses a callback function in order to condense an array into one value. However, .reduce() takes two parameters; the first is the accumulator and the second represents the current element of the array.

The value that is returned from this callback becomes the value of the accumulator. This means that when I evaluate the expression (addition in this example), the result will update the accumulator variable to its value. It is important to set the accumulator‘s initial value as the second parameter of the .reduce() method, otherwise it will default to the first element of the array which can cause unexpected results.

After that, I just need to divide the sum by the length of the array (array.length) and then return the value.

const getMean = (array) => {
  const sum = array.reduce((acc, el) => acc + el, 0);
  const mean = sum / array.length;
  return mean;
}

HOWEVER, I am able to clean this code up because of the ability to implicitly return values with an arrow function. This way the entire function can be written on one line instead of multiple lines with assigned variables.

All I need to do is remove the two variable declarations and add / array.length to the end of the reduce statement. Because of implicit return, the curly braces are no longer needed.

const getMean = (array) => array.reduce((acc, el) => acc + el, 0)/array.length;

With that cleaned up, I will add the getMean function to our calculate function so it can run when calculate() is called, and then I need to update the HTML to display the result of the calculation. I will do that by accessing the element that was given the “mean” id and changing its text content with our typical query selector process.

document.querySelector("#mean").textContent = mean;

The mean function is complete so now I move on to the median function. The median is the midpoint of a set of numbers. The first step to doing this is to sort the number set from least to greatest. There is another built in array method to arrange elements; .sort(). The .sort() method orders the elements in place, meaning it modifies the original array and you don’t need to create a variable to store a new array.

By default, .sort() converts the elements of an array into strings and then sorts them alphabetically (using Unicode) which is usually not what you want for numerical values. In order to circumvent the default, a callback function can be passed as an argument of .sort().

This callback function will compare two arguments (which represent the elements being compared) and return values based on if the first element should come before or after the second. A value greater than 0 means the first element should come AFTER the second element. A value less that 0 means that the first element should come BEFORE the second element. A returned value of 0 means that the elements should stay where they are.

Thoughts:

I am having some trouble understanding freecodecamp’s logic behind the following statement:
By default, the .sort() method converts the elements of an array into strings, then sorts them alphabetically. This works well for strings, but not so well for numbers. For example, 10 comes before 2 when sorted as strings, but 2 comes before 10 when sorted as numbers.

I understand that it will go through and evaluate each digit at a time, and of course 1 is less than 2 in both Unicode and just regular mathematical logic. But to my understanding, 10 having a second character (and 2 not) should automatically make it greater than 2, right? So their statement seems false.

I have created a post in the forum to see if someone can help me understand better.

I wanted to explain why 10 would be sorted before 2 if evaluated as a string, but I don’t quite understand and I’m trying to get further clarification. I guess it doesn’t matter all that much in the long run, but I would like to understand.

I think I’m going to stop here for today. Hopefully I have an explanation to my confusion by tomorrow and then I can document it.

Explanation To Ordering:

Maybe this was obvious to others, but the way it was explained to me is that since 1 < 2, and since 2 is only one digit, it only sorts based on the first digit, because there isn’t a second digit to compare the 0 to. It also sorts numbers one at a time, regardless of the amount of digits. By that I mean it sorts 20 as 2 and 0, not 20.

Not sure if I did a good job at explaining, but at least I understand what’s going on now.

Posted in web dev, freecodecamp, tutorial

Learn Advanced Array Methods – Part 1

Building a Statistics Calculator (Steps 1-9)

Freecodecamp.com Tutorial

**This is not meant to be a tutorial or a guide on how to complete the tutorial. This is just my thought process and notes as I go through the steps myself.**

Originally I wasn’t going to write about each individual exercise from freecodecamp, but I decided it would be good for me to do it so I can reinforce and better understand what I’m learning (hopefully). I wonder if I should go back and do the previous ones too, but I’ve gotten through a lot already.

I start off by assigning the user input to a variable, and then split it into an array of numbers with the .split() method and a regex to separate the numbers at the commas.

It is important to remember that the value of an input element always returns a string, even if the input type is “number.” The array is currently an array of strings, so it needs to be converted into the number type.

To do this, JavaScript has a built in .map() method. The .map() method creates a new array and does not change the original one.

The .map() method takes a callback function as its first argument. The callback function inside of .map() also takes multiple arguments, but the first one is referencing the current element that is being processed.

const calculate = () => {
const value = document.querySelector("#numbers").value;
const array = value.split(/,\s*/g);
const numbers = array.map(el => Number(el));
}

Thoughts:

I was a little confused at this part. freecodecamp uses “el” as the argument. I wasn’t sure if that is a built in thing (like “e” for event listeners) or if it is just the variable used because of referencing the current element. I looked it up and was able to discern that it is just a variable like any other and could have any name

The Number() constructor will return NaN if the value cannot be turned into a number. Arrays have a built in method to remove indicated values; .filter(). This will return a new array with the remaining values and will not change the original. The .filter() method also takes a callback function as its first argument. The .filter() method looks for a Boolean value from this callback. If true is returned, the value is added to the array.

Important: you cannot check for equality because NaN is not equal to itself.

There is a method called isNaN() that returns true if the argument is NaN. This can be used in .filter() to find the NaN values. Because I want the number values to be added to the array, I want to check if the result of isNaN() is NOT NaN. To do that I add the ! before isNaN(). That way if el is NaN, I’ll get false instead of true, therefore only adding numbers to the array.

Array methods can be chained together so they can be executed at the same time. That means I can just add the .filter() method after the .map() method.

Before:

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));
}

After:

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));;
}

I am done with the calculate function for now.

More to come.

Posted in freecodecamp, web dev

Palindrome Checker

I made a palindrome checker (prompt from freecodecamp, not a tutorial). I had some difficulty figuring out the Regex, but once that was sorted, things went pretty well.

I didn’t get around to doing any CSS but I am happy with the JS. I left in some of the things that didn’t work so I have reference for what I tried vs what code was successful. Added a few notes as well.

The goal going forward is to write posts as I work on things so that I can take notes on my thoughts and what works/doesn’t.

my palindrome checker

Next thing I’m working on is a Roman Numeral converter. I have some basic stuff down but I was trying to figure out how to simplify things. I probably should just finish and worry about simplifying later.

Posted in web dev

How it Started

I have this dream of being able to live off working part time. For awhile I considered if it was even possible. I started looking at careers that would pay enough for this dream to be possible.

There were a few guys back in my high school who were constantly getting in trouble for working around the blocks the school had up to keep kids from doing things they shouldn’t. I thought that was the coolest thing. Unfortunately back then and for a long time after, I thought I wasn’t smart enough to do anything computer related. Figured it was far beyond my comprehension so I never even tried. I wouldn’t have even known where to start.

College was a struggle. Once again I had considered going into something computer related. Once again I convinced myself I wasn’t smart enough. I even talked myself out of a comp sci elective that I had intended to take to see if it was something I could actually do.

I took a break from college for a few years even though I only had two semesters left. During that time I had worked in retail and a few warehouse print shops. I was so bored in these jobs. They were mindless and unfulfilling. I decided to finish up my degree that I had abandoned. I worked nights and took classes during the day, and slept in my car in between.

After my degree was finished I took a position doing customer service with the intention of applying to other jobs in the company as soon as I was able. At some point in all of this soul searching, I once again considered a career in computers. I began taking Web Development/Design courses at HACC.

HACC wasn’t great. I enjoyed most of the design courses. The professors for those were great. The coding/comp sci classes were awful though. They were just “watch this video and do this project,” and the videos weren’t even of him teaching. Must be nice to get paid to tell people to watch LinkedIn Learning.

I held out for too long, hoping for improvement. Of course nothing changed, so now I’ve got this pile of student loans with nothing to show for it. Once again I left the college program and decided to learn independently.

That’s where I am now. Trying to learn JavaScript off a Udemy course, books, and YouTube. It’s been hard, but I’m not giving up. The company I currently work for is laying off massive amounts of staff to send the jobs overseas. It is only a matter of time until mine is one of them.

I hope to be in a web dev position by 2025. It has been quite a journey. I hope I make it to the end.