JavaScript30: Day 4 - Solve Real Life challenges using Array Methods
Published: 2020-07-22 14:54:43

I've completed the Day 4 of Wes Bos <a href="https://javascript30.com/">JavaScript 30</a>.
Unlike the previous challenges, this one is solely focused on language features, no HTML/CSS. It's about using various array methods to manipulate data. 

## What did I solve?
Wes Bos posed some of the very interesting and real-life problems which can be solved by various array methods i.e. **Array.prototype.filter(), Array.prototype.map(), Array.prototype.sort(), Array.prototype.reduce()**

## My Experience
To be honest, this part made me feel at home😊 Being someone who had spent more time in the backend, it comes off as less intimidating than the CSS.
Having said that, I struggled with a couple of challenges especially the last one.

## The Challenge & My Learnings

Given Data:
```javascript

    const inventors = [
      { first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
      { first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
      { first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
      { first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
      { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
      { first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 },
      { first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
      { first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
      { first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
      { first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
      { first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
      { first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
    ];
```
+ **Filter the list of inventors for those who were born in the 1500's**
```js
const earlyInventors = inventors.filter((inventor) => inventor.year >= 1500 && inventor.year < 1600)
console.table(earlyInventors)
```
__The filter() method__- goes through each array element, check them against a certain condition, returns a new array with the elements that met the condition.

 + **Give us an array of the inventors first and last names**
```js
const inventorsName = inventors.map((inventor) => `${inventor.first} ${inventor.last}`)
 console.table(inventorsName)
```
__The map() method__- goes through each element, make them do a specific task, and returns a new array with the result.
Here, each inventor from the inventors array is passed to an arrow function that concatenates the first name and last names & returns an array with the results 

+ **How many years did all the inventors live all together?**
```js
const livingYear = inventors.reduce((acc, inventor) => acc + (inventor.passed - inventor.year), 0)
console.log(livingYear)
```
__The reduce() method__- executes a reducer function (that you provide) on each element of the array, resulting in a single output value. 
When you asked to accumulate something from an array, you probably wanna use reduce() method.
The reducer function that it executes can take up to 4 arguments; but commonly we use 2 arguments- accumulator and the current value.
The accumulator is the accumulated value previously returned in the last invocation & we usually initially initialize it to 0 (as the second argument of reduce() method).
And the current value is the current item being processed. 


+ **Sort the inventors by years lived**
```js
const byLivingYears = inventors.sort((a, b) => {
      return (a.passed - a.year) < (b.passed - b.year) ? 1 : -1
    })
    console.table(byLivingYears)
```
__The sort() method__- when provided with a compare function(which takes 2 arguments) like here, all non-undefined array elements are sorted according to the return value of the compare function. 
Return value -1 means, item comes first
Return value 1 means, item comes last
Return value 0 means, the item's position is unchanged
For example, aNumber < anotherNumber ? -1 : 1 
means aNumber will comes first if it less than the anotherNumber & vice versa.
 

+ *create a list of Boulevards in Paris that contain 'de' anywhere in the name
https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris *
```js
//select all the boulevards anchors form the page
    //#mw-content-text is found by inspection chrome dev tool
    const linksNode = document.querySelectorAll('#mw-content-text a')
    //convert the linksNode to array, find the text of the anchor tag & get all that includes 'de' in them
    const deBoulevard = [...linksNode].map(link => link.textContent).filter(boulevards => boulevards.includes('de'))
    console.table(deBoulevard)
```
To solve this we need to use multiple array methods as you can see.
First, we select the DOM element that contains all the anchor tags, using the mw-content-text id
As querySelectorAll() returns a nodeList we need to convert that to an array & then we used map() to find the text of the anchortags and then used filter() to filter by checking if they include 'de'

Now working with different data-
```js
    const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry',
      'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert',
      'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester',
      'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano',
      'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle',
      'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose',
      'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black, Elk', 'Blair, Robert',
      'Blair, Tony', 'Blake, William'
    ];
```
See all elements are string containing last and first name. They aren't structured correctly to work with. So if we need to do some operation on them we need to give them some shape based off of our challenge.

+ **Sort the people alphabetically by last name**

Sort the people alphabetically wouldn't be hard but as the first name and last name are packed in one single string, we need to find a way to split them. and do the operation accordingly.
```js
    const peopleByLastName = people.sort((a, b) => {
      //The split() method divides a String into an ordered list of substrings
      const [aLast, aFirst] = a.split(',')
      //const [aLast, aFirst] is called restructuring 
      //which makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
      const [bLast, bFirst] = b.split(',')
      return aLast > bLast ? 1 : -1 //in ascending order. smaller letter like 'a' comes first
    })
    console.log(peopleByLastName)

```

+ **Sum up the frequency of each of these-**
```js
 const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car',
      'truck'
    ];
```
This one is a bit tricky for me to solve. But the idea was pretty simple. The concept is each array item will be the object's key and its number of appearances will be it's key. For example, {car: 5, truck: 2}
1. create an empty object
2. loop through each array item; when a new item is found assigned it's value to 1 and if the item is existed previously increase it's value.

```js
   const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car',
      'truck'
    ];
    const vehicle = data.reduce(function (obj, item) {
      if (!obj.item) { //checks if the item is new
        obj.item = 0 //assign 0 for the new item
      }
      obj.item++ //icrement the value
      return obj
    }, {})
```

GitHub:
<p><a class="gh-btn" href="https://github.com/AKdeBerg/Day4_Js30_ArrayCardio">View on GitHub</a></p>