Wes Bos 的原始專案:JS30 Day04
專案目標:
熟悉陣列操作方法:filter()、map()、sort()、reduce()、from()、includes()、slice()。
此範例瀏覽器不會渲染出畫面,純粹用陣列操作方法來篩選出資料。
資料集
題目給了兩筆資料集,以下共有 8 道題目要從以下兩個資料集中篩選出目標物件資料。
|
|
第一題:篩選出生在 1500 年代的發明家
本題要從 inventors
資料集篩選出生在 1500 年代的發明家。
filter()
方法,會將陣列中的「每一個元素」帶入指定的函式內做判斷,透過 return
回傳判斷結果為 true
的元素,並組成新的陣列。
裡頭有一個函式 ( 必填 ) 和一個回傳函式裡的 this 參數 ( 選填 )。
函式內包含三個參數,第一個是每個元素的值 ( 必填 ),第二個是當前元素的索引值 ( 選填 ),第三個是當前的陣列 ( 選填 )。
let newArray = arr.filter(callback(element, index, array), thisArg);
本題解法
|
|
第二題:將發明家的姓氏、名字組合起來,回傳一個新陣列
map()
方法,會將陣列中的「每一個元素」帶入指定的函式內做判斷,透過 return
回傳運算後的結果,並組成新的陣列。
裡頭有一個函式 ( 必填 ) 和一個回傳函式裡的 this 參數 ( 選填 )。
函式內包含三個參數,第一個是每個元素的值 ( 必填 ),第二個是當前元素的索引值 ( 選填 ),第三個是當前的陣列 ( 選填 )。
map 語法:
let new_array = arr.map(callback(currentValue, index, array));
如果要使用 this 參數,則「不能使用」箭頭函式:
let new_array = arr.map(function callback(currentValue, index, array){}, thisArg);
本題解法
|
|
第三題:將發明家的生日由老到少排序
sort()
方法,會以一個排序用的判斷函式來對陣列的元素進行排序。判斷函式包含兩個參數,這兩個參數分別代表陣列裡第 n 個和第 n+1 個元素,透過比較第 n 和第 n+1 個元素的大小來進行排序。
如果不使用判斷函式的話,預設會將元素轉換成字串,並以首字母的 unicode 來判斷大小。
- 若 compareFunction(a, b) 的回傳值小於 0,則會把 a 排在小於 b 之索引的位置,即 a 排在 b 前面。
- 若 compareFunction(a, b) 回傳 0,則 a 與 b 皆不會改變彼此的順序,但會與其他全部的元素比較來排序。
- 若 compareFunction(a, b) 的回傳值大於 0,則會把 b 排在小於 a 之索引的位置,即 b 排在 a 前面。
arr.sort([compareFunction]);
由於回傳值為負數的話,a 會 排在 b的前面。所以升冪排序陣列的作法如下:
|
|
以此類推,降冪排序就改成 b-a
:
|
|
本題解法
|
|
第四題:把所有發明家的歲數加總
reduce()
方法是做數值累加,會將陣列中的「每一個元素」與下個元素相加,直到結束為止。
包含一個函式 ( 必填 ) 和初始值 ( 選填 )。
函式內有四個參數,第一個是累加器 ( 必填 ),第二個是當前元素 ( 必填 ),第三個是該元素的索引值 ( 選填 ),第四個是原本的陣列 ( 選填 )。
arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue);
本題解法
|
|
第五題:將所有發明家依歲數大小排序
本題使用第三題用過的 sort()
方法。
本題解法
|
|
第六題:篩選出中含有「de」的街道名稱
本題要從維基百科的一個資料頁面中撈取資料,並進行過濾篩選。
從該頁面中撈取出巴黎的街道名稱,並且篩選出中含有「de」的街道名稱。
本題解法
- 用
querySelectorAll
撈出頁面的資料 - 但撈出的資料是偽陣列 NodeList,必須用
from()
方法將其轉為真正的陣列 - 轉成陣列後,用
map()
方法取出 title 資料組成新陣列 - 最後用
filter()
和includes()
方法過濾出有 ‘de’ 字串的資料
|
|
第七題:將 people 資料集的人名依首字母排序
本題要將 people
資料集的人名依首字母進行排序。
除了使用第三題用過的 sort()
方法之外,也結合 slice()
方法擷取出字串的首字母。
slice(begin, end)
方法會回傳一個新陣列物件,為原陣列選擇之 begin 至 end(不含 end)部分的淺拷貝(shallow copy)。而原本的陣列將不會被修改。
arr.slice(begin, end);
begin 是選填,若省略了 begin ,則 slice 會從索引 0 開始提取。
也可使用負數索引,表示由陣列的最末項開始提取。
例如:slice(-2)
代表拷貝陣列中的最後兩個元素。
end 也是選填,若省略了 end,則 slice 會提取至陣列的最後一個元素。
若使用負數索引,表示由陣列的最末項開始提取。
例如:slice(2,-1)
代表拷貝陣列中第三個元素至倒數第二個元素。
本題解法
|
|
第八題:Reduce 練習
本題結合 if
判斷以及物件的特性,來加深對 reduce()
方法的進階應用。
把題目中所提供的陣列資料,依不同類別分別計算個數。
本題解法
|
|
延伸閱讀: