JS Array cardio

This is the fourth project of WesBos's JS30 series. To see the whole 30 part series, click here We will be creating a bunch of small exaples to play with various array methods such as map, reduce, filter and sort.

Here is the codepen with the starter files

Here is the data we have

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

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'];

So now we have a few lists and maps to work on (provided with the template), let's tackle the problems one by one!

Array.prototype.filter()

The [].filter(test_fn) method creates a new array with all elements that pass the condition implemented by the provided function (test_fn). Each element of the array is iterated upon and passed to test_fn as an argument, if test_fn returns a truthy for the element, it is included in the new list, if it returns a falsey, it is not. Learn more @ MDN docs.

Task : Filter the list of inventors for those who were born in the 1500's

const fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600))
console.table(fifteen)

Array.prototype.map()

The [].map(transform_fn) method creates a new array with the results of calling a provided function (transform_fn) on every element in the calling array. Learn more @ MDN docs.

Task : Give us an array of the inventor first and last names

const names = inventors.map(inventor => `${inventor.first} ${inventor.last}`)
console.log(names)

Array.prototype.sort()

The [].sort(cmp_fn) method sorts the elements of an array in place and returns the array. You can pass an optional function as an argument (cmp_fn), which will be used to compare two elements with each other. The cmp_fn(a,b) takes in two arguments - each being an element of the array being sorted. The compare function - * should return a value lesser than 0 if 'a < b'. ('a' will be placed at a lower index than 'b') * should return a value equal to 0 if 'a == b' ('a' and 'b' will remain where they are wrt each other) * should return a value greater than 0 if 'a > b' ('b' will be places at a lower index than 'a')

Learn more @ MDN docs

Task : Sort the inventors by birthdate, oldest to youngest

const sorted = inventors.sort((a, b) => b.year - a.year)
console.table(sorted)

Array.prototype.reduce()

The [].reduce(acc_fn [, init_val]) method applies a function (acc_fn) against an accumulator (initial value being the first element of the array unless init_val is passed) and each element in the array (from left to right) to reduce it to a single value. Example -

const arr = [1, 2, 3, 4];

// 5 + 1 + 2 + 3 + 4
x = arr.reduce((accumulator, currElem) => accumulator + currElem, 5));
// x = 15

Learn more @ MDN docs

Task: How many years did all the inventors live?

// acc at any given point of time is the sum of all ages iterated until then. initial value is 0
const years = inventors.reduce((acc, inventor)=> acc + (inventor.passed -inventor.year), 0)
console.log(years)

Exercise with map and filter

Task : Create a list of Boulevards in Paris that contain 'de' anywhere in the name. Use this webpage https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris

Steps : * Select all the <a> elements under div.mw-category from the page. * Convert the NodeList into an array * From the above array, get the array of names of the Boulevards * Filter the ones with 'de' in it

const category = document.querySelector('.mw-category a');
const links = Array.from(category);
const de = links
            .map(link => link.textContent)
            .filter(streetName => streetName.includes('de'));

Sort exercise

Task : Sort the people alphabetically by last name

In the comparision function, just split by ", " and compare the first elements in the arrays, if p1's last name is greater than p2's last name, return 1 indicating that p1 is greater, else return -1 indicating that p2 is greater.

const sorted = people.sort((p1, p2) => {
    return p1.split(', ')[0] > p2.split(', ')[0]? 1: -1
})
console.table(sorted)

Reduce Exercise

Task : Sum up the instances of each element in the following list. Basically return a object with the name and count of the words that appear in the list.

const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck', 'pogostick'];

Solution

const transport = data.reduce((countMap, elem) => {
    countMap[elem] = countMap[elem]? countMap[elem]+1 : 1
    return countMap
}, {})


// alternatively using forEach, which actually seems more well suited
trans = {}
data.forEach(elem => (trans[elem] = trans[elem]? trans[elem]+1 : 1) )

Thats it for this tutorial!