Published on

Day4: Array Cardio 1 💪

Authors
js30

專案介紹: 練習 array 的應用,包含 filter 、 map 、 sort 、 reduce

作品頁面: https://iris1114.github.io/javascript30/04_Array-Cardio-Day-1/index.html (無畫面,請打開 console)

題目資料

題目給了 3 組資料,總共 8 道題目, inventors 資料用於 1-5 題 , people 資料用於第 7 題, data 資料用在第 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

  • 方法 : 使用 filter() 去篩選符合條件的元素。filter() 會建立新陣列並回傳符合的元素。

  • Ans:

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

  • 方法: 使用 map() 回傳 inventors 的 first last names 。map() 也會產生新陣列,並回傳你所需要的值。

  • Ans:

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

console.table(ans2)

Q3. Sort the inventors by birthdate, oldest to youngest

  • 方法: 使用 sort() 排序生日。sort() 則不會產生新陣列, 對原陣列進行排序,並回傳此陣列。 但要注意的是排序不一定穩定,排序順序是根據字串的 Unicode 編碼位置而定。

  • Ans:

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

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

以上例子,不是我們預想的排序,因為元素將被轉換為字串並以 Unicode 編碼位置進行比較來排序。所以這時候我們就需要使用compareFunction 來做比較。

語法: arr.sort([compareFunction])

如果 compareFunction 被應用,陣列元素們將根據比較函式之回傳值來排序。如果 a 和 b 為被比較之兩元素, a 小於 b ,則 a 排在 b 前面。 a 大於 b, 則 a 排在 b 後面。回傳 0,則 a 與 b 皆不會改變彼此的順序。

函式會是以下形式(用於第 7 題作法):

function compare(a, b) {
  if (在某排序標準下 a 小於 b) {
    return -1;
  }
  if (在某排序標準下 a 大於 b) {
    return 1;
  }
  // a 必須等於 b
  return 0;
}

為了比較數字而不是字串,比較函式可以僅僅利用 a 減 b。以下函式將會升冪排序陣列(用於第 3 題、第 5 題作法):

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

因為第三題只需要數字比較,我這邊就使用 a 減 b 進行排序。


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

  • 方法: 使用 reduce 來計算他們總共幾歲。reduce() 跟其他陣列方法(例如:map、filter)的差別是它會 return 一個值,而不是一個新陣列。不過一般我們也可以使用 forEach 進行加總也可以。

  • Ans:

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

console.log(ans4)

//forEach 方法

let total = 0
inventors.forEach((inventor) => {
  total += inventor.passed - inventor.year
})
console.log(total)
  • 補充

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

accumulator:經由個別 currentValue 加總的累計值

initialValue:預設值,放在 function 的最後方,非必填

若未提供預設值:

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

上述範例若未提供預設值,accumulator(累計值)就會取陣列的第一個元素也就是 1,而 currentValue 就會從陣列的第二個值開始 loop。

若加上預設值 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

他就會從 0 開始加起,再繼續從陣列第一個值 loop 下去。

他也可用於合併陣列 :

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

  • 方法:使用 sort() 排序他們的壽命。
  • Ans:
//新增他們壽命,來檢查排序是否有錯誤
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)
  • 第三題已有針對 sort() 進行補充,這題多了計算壽命的部分。

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

  • 方法: 從這個網站中 list 找出含'de'字眼的街道名稱。 先用 querySelectorAll 找出所有 list , 但找到的 list 不是 array, 他是 nodelist, 無法進行 mapping, 所以可以使用 Array.from 將 nodeList 轉為 Array。 或是 nodelist 也可以使用 forEach 跑 loop。
// method1
const array = []
const lists = document.querySelectorAll('.mw-category li a') //nodelist 不是陣列,但可以用 forEach 跑迭代, 可以用 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

  • 方法: 使用 people 資料的 last name 進行排序, 一樣是使用 sort, 可參考第三題補充, 但因為他是文字, 使用我們 compareFunction(a, b) 函式進行排序。

  • Ans:

const ans7 = people.sort((a, b) => {
  const [aFirtst, aLast] = a.split(', ')
  const [bFirtst, 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

  • 方法: 使用 data 資料的來計算裡面相同東西的數量,剛剛上面 reduce() 沒提到的應用, 他也可以計算相同字串的數量並以物件呈現。

  • Ans:

const ans8 = data.reduce((obj, content) => {
  if (!obj[content]) {
    //如果沒有的話則為0
    obj[content] = 0
  }
  obj[content] += 1 //如果沒有的相同的則+1

  return obj
}, {}) //預設給個空object

console.log(ans8)

這篇部落格花我好多時間,比寫 code 時間還久很多很多 XD 終於完成,繼續加油!