Happylab Logo
Published on

Day4: Array Cardio 1 💪

Authors
js30

Project Introduction: Practice array methods including filter, map, sort, and reduce

Project Page: https://iris1114.github.io/javascript30/04_Array-Cardio-Day-1/index.html (no visual interface, please open console)

Sample Data

The exercise provides 3 sets of data with 8 questions total. The inventors data is used for questions 1-5, people data for question 7, and data array for question 8.

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 = [
  'Bernhard, Sandra',
  'Bethea, Erin',
  'Becker, Carl',
  'Bentsen, Lloyd',
  'Beckett, Samuel',
  'Blake, William',
  'Berger, Ric',
  'Beddoes, Mick',
  'Beethoven, Ludwig',
  'Belloc, Hilaire',
  'Begin, Menachem',
  'Bellow, Saul',
  'Benchley, Robert',
  'Blair, Robert',
  'Benenson, Peter',
  'Benjamin, Walter',
  'Berlin, Irving',
  'Benn, Tony',
  'Benson, Leana',
  'Bent, Silas',
  'Berle, Milton',
  'Berry, Halle',
  'Biko, Steve',
  'Beck, Glenn',
  'Bergman, Ingmar',
  'Black, Elk',
  'Berio, Luciano',
  'Berne, Eric',
  'Berra, Yogi',
  'Berry, Wendell',
  'Bevan, Aneurin',
  'Ben-Gurion, David',
  'Bevel, Ken',
  'Biden, Joseph',
  'Bennington, Chester',
  'Bierce, Ambrose',
  'Billings, Josh',
  'Birrell, Augustine',
  'Blair, Tony',
  'Beecher, Henry',
  'Biondo, Frank',
]

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

Q1. Filter the list of inventors for those who were born in the 1500's

  • Method: Use filter() to screen elements that meet the condition. filter() creates a new array and returns matching elements.

  • Answer:

const ans1 = inventors.filter((inventor) => {
  if (inventor.year >= 1500 && inventor.year < 1600) {
    return inventor
  }
})

console.table(ans1)

Q2. Give us an array of the inventors first and last names

  • Method: Use map() to return inventors' first and last names. map() also creates a new array and returns the values you need.

  • Answer:

const ans2 = inventors.map((inventor) => {
  return `${inventor.first} ${inventor.last}`
})

console.table(ans2)

Q3. Sort the inventors by birthdate, oldest to youngest

  • Method: Use sort() to sort by birth year. sort() doesn't create a new array but sorts the original array and returns it. Note that sorting isn't always stable - it's based on the Unicode values of strings.

  • Answer:

const ans3 = inventors.sort((a, b) => {
  return a.year - b.year
})

console.table(ans3)
  • Additional Note:
const array1 = [1, 30, 4, 21, 100000]
array1.sort()
console.log(array1)
// expected output: Array [1, 100000, 21, 30, 4]

The example above doesn't sort as expected because elements are converted to strings and compared by Unicode values. This is why we need to use a compareFunction.

Syntax: arr.sort([compareFunction])

If compareFunction is used, array elements are sorted according to its return value. If a is less than b, a comes before b. If a is greater than b, a comes after b. If they're equal, their order remains unchanged.

The function takes this form (used in Q7):

function compare(a, b) {
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by some ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

For comparing numbers, the comparison function can simply subtract b from a. This function will sort the array in ascending order (used in Q3 and Q5):

function compareNumbers(a, b) {
  return a - b
}

Since Q3 only needs number comparison, we used simple subtraction for sorting.


Q4. How many years did all the inventors live all together?

  • Method: Use reduce to calculate their total age. reduce() differs from other array methods (like map, filter) as it returns a single value, not a new array. We could also use forEach for summation.

  • Answer:

const ans4 = inventors.reduce((total, inventor) => {
  return total + (inventor.passed - inventor.year)
}, 0) // Start from 0

console.log(ans4)

// forEach method
let total = 0
inventors.forEach((inventor) => {
  total += inventor.passed - inventor.year
})
console.log(total)
  • Additional Notes

Syntax: Array.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)

accumulator: The accumulated value from each currentValue initialValue: Optional starting value, placed at the end of the function

Without initialValue:

const arr = [1, 2, 3, 4, 5]
const reduceArr = arr.reduce((accumulator, currentValue) => {
  return accumulator + currentValue
})
console.log(reduceArr) // 15

If no initialValue is provided, accumulator takes the first array element, and currentValue starts from the second element.

With initialValue 0:

const arr = [1, 2, 3, 4, 5]
const reduceArr = arr.reduce((accumulator, currentValue) => {
  console.log(accumulator) // 0, 1, 3, 6, 10
  console.log(currentValue) // 1, 2, 3, 4, 5
  return accumulator + currentValue
}, 0)
console.log(reduceArr) // 15

It starts adding from 0 and loops through array values.

It can also be used to merge arrays:

const arr = [
  ['a', 'b'],
  ['c', 'd'],
  ['e', 'f'],
]
const reduceArr = arr.reduce((accumulator, currentValue) => {
  return accumulator.concat(currentValue)
}, [])
console.log(reduceArr) // ['a', 'b', 'c', 'd', 'e', 'f']

Q5. Sort the inventors by years lived

  • Method: Use sort() to sort by their lifespan.
  • Answer:
// Add age property to check sorting accuracy
inventors.forEach((inventor) => {
  inventor.age = inventor.passed - inventor.year
})

const ans5 = inventors.sort((a, b) => {
  return a.passed - a.year - (b.passed - b.year)
})

console.table(ans5)
  • See Q3 for sort() explanation. This question adds age calculation.

Q6. Create a list of Boulevards in Paris that contain 'de' anywhere in the name

  • Method: From this website, find street names containing 'de'. First use querySelectorAll to find all lists, but note that it returns a NodeList, not an array. NodeList can't be mapped, so use Array.from to convert it to an array. NodeList can use forEach for iteration.
// method1
const array = []
const lists = document.querySelectorAll('.mw-category li a') // NodeList isn't an array but can use forEach. Can use Array.from

lists.forEach((list) => {
  array.push(list.title)
})

const ans6 = array.filter((title) => {
  return title.indexOf('de') !== -1
})

console.log(ans6)

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

Q7. Sort the people alphabetically by last name

  • Method: Sort the people data by last name using sort(). See Q3 for sort() explanation, but since we're dealing with text, we use the compareFunction(a, b) format.

  • Answer:

const ans7 = people.sort((a, b) => {
  const [aFirst, aLast] = a.split(', ')
  const [bFirst, bLast] = b.split(', ')

  return aLast > bLast ? 1 : aLast < bLast ? -1 : 0
})

console.log('7. Sort the people alphabetically by last name')
console.log(ans7)

Q8. Sum up the instances of each of these

  • Method: Use the data array to count occurrences of each item. Another application of reduce() not mentioned earlier - it can count string occurrences and present them as an object.

  • Answer:

const ans8 = data.reduce((obj, content) => {
  if (!obj[content]) {
    // If doesn't exist, set to 0
    obj[content] = 0
  }
  obj[content] += 1 // Add 1 if same item found

  return obj
}, {}) // Start with empty object

console.log(ans8)

This blog post took me much longer than coding - much, much longer XD Finally completed, keep going!