# Day 4:Array Cardio Day 1 [竹白記事本](https://chupainotebook.blogspot.com/),Javascript 30,紀錄。 ###### tags: `Javascript 30` ## 實現效果 陣列資料處理練習。 - [原始碼](https://github.com/chupai/JS30/tree/master/source_code/Day04) ## 重點 沒啥重點,就資料處理。 ## 基礎語法 ### JavaScrit - `Array.prototype` - `filter()` - `map()` - `sort()` - `reduce()` >[陣列與批次操作](https://hackmd.io/7_PfOokERX-kgUUL4UQOZQ) ## 說明 ### 1. 資料 共有三筆資料: - `inventors` - `people` - `data` ```javascript 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']; const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ]; ``` ### 2. 小技巧 如果要查看資料, [`console.table()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Console/table) 會比 `console.log()` 來得直觀,它可將資料以表格的形式顯示, ## 實作 ### 問題 1 Filter the list of inventors for those who were born in the 1500's. 從 `inventors` 篩選 15世紀(1500-1599)出生的。 ```javascript let ans1 =inventors.filter(function(inventor) { return inventor.year >= 1500 && inventor.year < 1600; }); console.table(ans1); ``` `filter()` 會回傳一個新陣列,其條件是 `return` 後方為 `true` 的物件,很適合用在搜尋符合條件的資料。 使用 [ES6 箭頭函式](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions),更簡化 ```javascript let ans1 = inventors.filter( inventor => inventor.year >= 1500 && inventor.year < 1600 ); ``` ### 問題 2 Give us an array of the inventors' first and last names. 將 `inventors` 的 `first` 與 `last` 組合成一個陣列。 ```javascript let ans2 = inventors.map(inventor => `${inventor.first} ${inventor.last}`); ``` `map()` 需要回傳一個值,他會透過函式內所回傳的值組合成一個新陣列。 - 如果不回傳則是 `undefined` - 回傳數量等於原始陣列的長度 `map()` 與 `forEach()` 差別: `forEach()` 不會額外回傳值,只單純執行每個陣列內的物件或值。 如果要使用 `forEach()` 達成一樣功能,就要新增一個空陣列,並使用 `push` 將內容丟進空陣列。 ```javascript let ans2 = []; inventors.forEach(inventor => ans2.push(`${inventor.first} ${inventor.last}`) ); ``` ### 問題 3 Sort the inventors by birthdate, oldest to youngest. 將 `inventor` 依據生日由大至小排序。 ```javascript let ans3 = inventors.sort((a, b) => a.year - b.year); ``` `sort()` 方法會原地(in place)對一個陣列的所有元素進行排序,並回傳此陣列。 排序不一定是穩定的,各家瀏覽器都不同,可以參考 **[從 Array 的 sort 方法,聊到各瀏覽器的實作,沒想到 Chrome 和FireFox 的排序如此不同](https://medium.com/@realdennis/javascript-%E5%BE%9Earray%E7%9A%84sort%E6%96%B9%E6%B3%95-%E8%81%8A%E5%88%B0%E5%90%84%E5%AE%B6%E7%80%8F%E8%A6%BD%E5%99%A8%E7%9A%84%E5%AF%A6%E4%BD%9C%E7%AE%97%E6%B3%95-c23a335b1b80)** 這篇文章。 ### 問題 4 How many years did all the inventors live? `inventor` 在世期間總和? ```javascript let total = inventors.reduce((total, inventor) => { return total + inventor.passed - inventor.year; }, 0); ``` [`reduce()`](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。 詳細可參考 [JavaScript 中 `reduce()` 方法不完全指南](https://aotu.io/notes/2016/04/14/js-reduce/index.html)。 不用 `reduce()` 的作法: ```javascript let total = 0; inventors.forEach(inventor => { total += inventor.passed - inventor.year; }); ``` ### 問題 5 Sort the inventors by years lived. 將 `inventor` 依據年齡由大至小排序所有的。 ```javascript let ans5 = inventors.sort((a, b) => { return (a.passed - a.year) - (b.passed - b.year); }); ``` ### 問題 6 create a list of Boulevards in Paris that contain 'de' anywhere in the name. 到 [`wiki`](https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris) 網頁,列出所有包含 `'de'` 的路名。 ```javascript 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')); ``` `querySelectorAll()` 出來的是 `NodeList`,沒有 `map()` 方法,所以要先用 `Array.from()` 轉陣列。 [`include()`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)方法用來判斷一個陣列是否包含一個指定的值,根據情況,如果包含則返回 `true`,否則返 `false`。 ### 問題 7 Sort the people alphabetically by last name. `people` 的 `lastName` 依據字母順序排序。 ```javascript let ans7 = people.sort((a, b) => { let [aFirst, aLast] = a.split(', '); let [bFirst, bLast] = b.split(', '); return aLast > bLast ? 1 : bLast > aLast ? -1 : 0; }); // 或是 let ans7 = people.sort((a, b) => { let aAry = a.split(', '); let bAry = b.split(', '); return aAry[1] > bAry[1] ? 1 : bAry[1] > aAry[1] ? -1 : 0; }); ``` 使用 `split()` 將名字拆開,再來判斷順序。 [`split()`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/split) 方法使用指定的分隔符字符串將一個 String 對象分割成字串陣列,以將字符串分隔為子字符串,以確定每個拆分的位置。 ### 問題 8 Sum up the instances of each of these. 分別計算 `data` 內每個種類的數量。 首先將累計器的預設值設為空物件 `{}`。 ```javascript let ans8 = data.reduce((obj, item) => { }, {}); ``` 接著將物件建立出來,並加 `1`。 ```javascript let ans8 = data.reduce((obj, item) => { obj[item] = 0 obj[item]++; return obj }, {}); console.log( ans8 ); // Object { // bike: 0, // car: 0, // truck: 0, // van: 0, // walk: 0 // } ``` 但這樣子遇到重複的資料時,不會累加,只會重新將它重設為 `0` 並加 `1`。 因此需要加上判斷式: ```javascript if(!obj[item]){ obj[item] = 0; } ``` 當 `obj[item]` 不存在就其建立並將值設為 `0`。 這樣遇到重複的資料時,就不會又重設為 `0`,而會累加次數。 ```javascript let ans8 = data.reduce((obj, item) => { if(!obj[item]){ obj[item] = 0; } obj[item]++; return obj }, {}); console.log( ans8 ); // Object { // bike: 2, // car: 5, // truck: 3, // van: 2, // walk: 2 // } ```