Please enable Javascript to view the contents

【JS30系列】Day 04:Array Cardio Day 1

 ·  ☕ 5 分鐘 · 👀... 閱讀

Wes Bos 的原始專案:JS30 Day04


專案目標:

熟悉陣列操作方法:filter()、map()、sort()、reduce()、from()、includes()、slice()。
此範例瀏覽器不會渲染出畫面,純粹用陣列操作方法來篩選出資料。

實作成果


資料集

題目給了兩筆資料集,以下共有 8 道題目要從以下兩個資料集中篩選出目標物件資料。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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'
];


第一題:篩選出生在 1500 年代的發明家

本題要從 inventors 資料集篩選出生在 1500 年代的發明家。

filter() 方法,會將陣列中的「每一個元素」帶入指定的函式內做判斷,透過 return 回傳判斷結果為 true 的元素,並組成新的陣列。

裡頭有一個函式 ( 必填 ) 和一個回傳函式裡的 this 參數 ( 選填 )。
函式內包含三個參數,第一個是每個元素的值 ( 必填 ),第二個是當前元素的索引值 ( 選填 ),第三個是當前的陣列 ( 選填 )。

本題解法
1
2
3
4
5
6
7
// Array.prototype.filter()
// 1. Filter the list of inventors for those who were born in the 1500's

let inventors_1500s = inventors.filter(el => {
  return el.year<1600 && el.year>1500;
});
console.log(inventors_1500s);


第二題:將發明家的姓氏、名字組合起來,回傳一個新陣列

map() 方法,會將陣列中的「每一個元素」帶入指定的函式內做判斷,透過 return 回傳運算後的結果,並組成新的陣列。

裡頭有一個函式 ( 必填 ) 和一個回傳函式裡的 this 參數 ( 選填 )。
函式內包含三個參數,第一個是每個元素的值 ( 必填 ),第二個是當前元素的索引值 ( 選填 ),第三個是當前的陣列 ( 選填 )。

本題解法
1
2
3
4
5
6
7
// Array.prototype.map()
// 2. Give us an array of the inventors first and last names

let inventors_name = inventors.map(el => {
  return el.first+' '+el.last;
});
console.log(inventors_name);


第三題:將發明家的生日由老到少排序

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 前面。

由於回傳值為負數的話,a 會 排在 b的前面。所以升冪排序陣列的作法如下:

1
2
3
function compareNumbers(a, b) {
  return a - b;
}

以此類推,降冪排序就改成 b-a

1
2
3
function compareNumbers(a, b) {
  return b - a;
}
本題解法
1
2
3
4
5
6
7
// Array.prototype.sort()
// 3. Sort the inventors by birthdate, oldest to youngest

let inventors_birth = inventors.sort(function(a,b){
  return a.year - b.year;
});
console.log(inventors_birth);


第四題:把所有發明家的歲數加總

reduce() 方法是做數值累加,會將陣列中的「每一個元素」與下個元素相加,直到結束為止。

包含一個函式 ( 必填 ) 和初始值 ( 選填 )。
函式內有四個參數,第一個是累加器 ( 必填 ),第二個是當前元素 ( 必填 ),第三個是該元素的索引值 ( 選填 ),第四個是原本的陣列 ( 選填 )。

本題解法
1
2
3
4
5
6
7
// Array.prototype.reduce()
// 4. How many years did all the inventors live all together?

let inventors_live = inventors.reduce(function(total, el){
  return total + (el.passed - el.year);
}, 0);
console.log(inventors_live);


第五題:將所有發明家依歲數大小排序

本題使用第三題用過的 sort() 方法。

本題解法
1
2
3
4
5
6
// 5. Sort the inventors by years lived

let inventors_age = inventors.sort(function(a,b){
  return (b.passed - b.year) - (a.passed - a.year);
});
console.log(inventors_age);


第六題:篩選出中含有「de」的街道名稱

本題要從維基百科的一個資料頁面中撈取資料,並進行過濾篩選。

從該頁面中撈取出巴黎的街道名稱,並且篩選出中含有「de」的街道名稱。

本題解法
  1. querySelectorAll 撈出頁面的資料
  2. 但撈出的資料是偽陣列 NodeList,必須用 from() 方法將其轉為真正的陣列
  3. 轉成陣列後,用 map() 方法取出 title 資料組成新陣列
  4. 最後用 filter()includes() 方法過濾出有 ‘de’ 字串的資料
1
2
3
4
5
6
7
8
// 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name
// https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris

let source = document.querySelectorAll('.mw-category-group li a');
let toArr = Array.from(source);   // 將偽陣列 NodeList 用 from() 方法轉為真正的陣列
let newArr = toArr.map(el=>{return el.title;});   // 用 map() 方法取出 title 資料組成新陣列
let resultArr = newArr.filter(el=>{return el.includes('de');});   //用 filter() 和 includes() 方法過濾出有 'de' 字串的資料
console.log(resultArr);


第七題:將 people 資料集的人名依首字母排序

本題要將 people 資料集的人名依首字母進行排序。
除了使用第三題用過的 sort() 方法之外,也結合 slice() 方法擷取出字串的首字母。

slice(begin, end) 方法會回傳一個新陣列物件,為原陣列選擇之 begin 至 end(不含 end)部分的淺拷貝(shallow copy)。而原本的陣列將不會被修改。

begin 是選填,若省略了 begin ,則 slice 會從索引 0 開始提取。
也可使用負數索引,表示由陣列的最末項開始提取。
例如:slice(-2) 代表拷貝陣列中的最後兩個元素。

end 也是選填,若省略了 end,則 slice 會提取至陣列的最後一個元素。
若使用負數索引,表示由陣列的最末項開始提取。
例如:slice(2,-1) 代表拷貝陣列中第三個元素至倒數第二個元素。

本題解法
1
2
3
4
5
6
7
8
9
// 7. sort Exercise
// Sort the people alphabetically by last name

let alphaArr = people.sort(function(a,b){
  let A = a.slice(0, 1);
  let B = b.slice(0, 1);
  return A>B ? 1 : B>A ? -1 : 0;
});
console.log(alphaArr);


第八題:Reduce 練習

本題結合 if 判斷以及物件的特性,來加深對 reduce() 方法的進階應用。

把題目中所提供的陣列資料,依不同類別分別計算個數。

本題解法
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 8. Reduce Exercise
// Sum up the instances of each of these

const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];
let total = 0;
let calcItems = data.reduce((obj,el)=>{
  if(!obj[el]){
    obj[el] = 1;
    total++;
  } else{
    obj[el]+=1;
    total++;
  }
  return obj;
},{});
console.log(calcItems);
console.log(total);


延伸閱讀:



分享

Sylvia-H
作者
Sylvia-H
Web Developer / F2E 前端筆記

comments powered by Disqus