Array method! go go go!
任務拆解
- Array method
    
- fliter()
 - map()
 - sort()
 - reduce()
 
 
講師設計幾組可以使用上述method的情境,比官方範例會再有感一點~
filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
by -(MDN web docs)(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
一個一個元素被
指定的測試函數篩選過濾,根據回傳值是true/false決定是保留還是丟掉,最後返回新陣列。
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
//output: Array ["exuberant", "destruction", "present"]
小鴨說code: 宣告words變數,記憶體位址指向一陣列,其中共有6個元素。宣告一變數result用來存結果,使用陣列filter method,測試每一個傳入的element長度是否大於6,若為true則存入result陣列中。
Filter the list of inventors for those who were born in the 1500’s
篩選出1500~1599年出生的人
 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 }
    ];
let result1 = inventors.filter((item) => {
      return item.year > 1500 && item.year < 1600;
    });
  
 // or 講師解
 
const fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600));
// 寫成arrow function 真的很乾淨
// ()=>{}
// 沒有傳入參數還是要有空括號()
// 只是回傳某個值,return可以省
// 只有一個參數,可以省()不寫

ps. console.table將資料以表格形式呈現,乾淨無誤!
map()
The
**map()**method creates a new array populated with the results of calling a provided function on every element in the calling array.by -(MDN web docs)(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
一個一個元素透過
運算函式再回傳一個新的值,組成新的陣列。陣列長度不變!一對一重組一個陣列,沒回傳值就給
undefined!
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
小鴨說code:宣告一變數array1,位址指向一物件,內容元素依序是1,4,9,16。使用陣列的map method,回傳結果存入map1變數中。每一個傳入的元素x,return x X 2!
Give us an array of the inventors first and last names
取得一陣列,內容為每個發明家first name和 last name的組合!
 let nameArray = inventors.map(item => item.first + ' ' + item.last);
 
 // or 講師解
  const fullNames = inventors.map(inventor => `${inventor.first} ${inventor.last}`);
  
// Template strings!!
// 使用``反引號
// 換行再也不用\n
// ${}可內嵌變數 or 運算式
sort()
The
**sort()**method sorts the elements of an array in place and returns the sorted array.by -MDN web docs
直接in place改變原陣列!!
arr.sort([compareFunction])
可以傳入一comparefunction,省略不寫的話,是依據每元素轉成字串後的unicode進行排序
常見的雷是:數字排序,照數值9會在80前,但因為預設排序會先轉成字串用Unicode排序,變成80在9之前

推[JavaScript] 從 Array 的 sort 方法,聊到各瀏覽器的實作,沒想到 Chrome 和FireFox 的排序如此不同
有關compare function寫得很詳細!
節錄重點如下:
function compare(a, b) {
  if (在某排序標準下 a 小於 b) {
    return -1;
  }
  if (在某排序標準下 a 大於 b) {
    return 1;
  }
  // a 必須等於 b
  return 0;
}
另一個要小心的就是a,b分別是誰?
in chrome:

in Firefox:

懶人記法:
// 想要由小往大
arr.sort((a,b)=>a-b);
// 想要由大至小
arr.sort((a,b)=>b-a);
Sort the inventors by birthdate, oldest to youngest
出生年份由小到大排~
 inventors.sort(function (a, b) {
      return a.year - b.year;
    })
    
// or 講師解
 const ordered = inventors.sort((a, b) => a.year > b.year ? 1 : -1);

reduce()
The
**reduce()**method executes a reducer function (that you provide) on each element of the array, resulting in single output value.by -MDN web docs
和前次回傳的值再進行運算,最終回傳一個運算結果!
arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
accumulator:累加總值, initialvalue:累加前的初始總值, currentvalue:當下元素/變數
小鴨說code: 定義一reducer function,為每次累加當下變數進accumulator中!
How many years did all the inventors live all together?
加總全部人的歲數
const years = inventors
      .map(inventor => inventor.passed - inventor.year)
      .reduce((acc, cur) => acc + cur, 0);
    console.log(years);
// 講師解
 const totalYears = inventors.reduce((total, inventor) => {
      return total + (inventor.passed - inventor.year);
    }, 0);
// 每次計算歲數的結果累計至total中!
綜合情境
Sort the inventors by years lived
將實際歲數排序
 const oldest = inventors
      .sort((a, b) => (b.passed - b.year) - (a.passed - a.year));
    console.table(oldest);
    
// 講師解
    const oldest = inventors.sort(function(a, b) {
      const lastInventor = a.passed - a.year;
      const nextInventor = b.passed - b.year;
      return lastInventor > nextInventor ? -1 : 1;
    });
    console.table(oldest);
create a list of Boulevards in Paris that contain ‘de’ anywhere in the name
取得含有de的名稱,目標資料 https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris
- 先找出目標來源的
classname 

- 觀察結構
 

  const category = document.querySelector('.mw-category');
    const links = Array.from(category.querySelectorAll('a'))
    const text = links.map(item => item.textContent)
      .filter(name => name.indexOf('de') > -1);
    console.log(text);
 
 // 講師解
 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'));
sort Exercise Sort the people alphabetically by last name
根據每個人的last name字母做排序
 const alpha = people.sort((pre, next) => {
      const [preLast, nextLast] = [pre.split(', ')[0], next.split(', ')[0]];
      return preLast > nextLast ? 1 : -1;
    })
    
// 講師解
const alpha = people.sort((lastOne, nextOne) => {
      const [aLast, aFirst] = lastOne.split(', ');
      const [bLast, bFirst] = nextOne.split(', ');
      return aLast > bLast ? 1 : -1;
    });
    console.log(alpha);
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'
    ];
 const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car',
      'truck'
    ];
    const sum = data.reduce((obj, cur) => {
      if (!obj[cur]) {
        obj[cur] = 0;
      }
      obj[cur]++;
      return obj;
    }, {})
    console.log(sum);
    
 // 講師解
 const transportation = data.reduce(function (obj, item) {
      if (!obj[item]) {
        obj[item] = 0;
      }
      obj[item]++;
      return obj;
    }, {});
小結&感想
- Array.prototype
    
- filter()
        
- 回傳新陣列
 
 - map()
        
- 回傳新陣列
 
 - sort()
        
- 就地改變陣列
 
 - reduce()
        
- 回傳累計的accumulator
 
 
 - filter()
        
 
寫code習慣很難改過來…..,落落長的寫法要慢慢精簡化!
講師的範例很實在,覺得會更知道要怎麼在實際的專案派上用場。
附上一張emoji版的講解

圖摘自Map, filter, and reduce explained using emoji
參考來源
JavaScript 陣列處理方法 [filter(), find(), forEach(), map(), every(), some(), reduce()]
[JavaScript] 從 Array 的 sort 方法,聊到各瀏覽器的實作,沒想到 Chrome 和FireFox 的排序如此不同