Try   HackMD

Day 4:Array Cardio Day 1

竹白記事本,Javascript 30,紀錄。

tags: Javascript 30

實現效果

陣列資料處理練習。

重點

沒啥重點,就資料處理。

基礎語法

JavaScrit

  • Array.prototype
    • filter()
    • map()
    • sort()
    • reduce()

陣列與批次操作

說明

1. 資料

共有三筆資料:

  • inventors
  • people
  • data
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() 會比 console.log() 來得直觀,它可將資料以表格的形式顯示,

實作

問題 1

Filter the list of inventors for those who were born in the 1500's.
inventors 篩選 15世紀(1500-1599)出生的。

let ans1 =inventors.filter(function(inventor) {
  return inventor.year >= 1500 && inventor.year < 1600;
});

console.table(ans1);

filter() 會回傳一個新陣列,其條件是 return 後方為 true 的物件,很適合用在搜尋符合條件的資料。

使用 ES6 箭頭函式,更簡化

let ans1 = inventors.filter(
  inventor => inventor.year >= 1500 && inventor.year < 1600
);

問題 2

Give us an array of the inventors' first and last names.
inventorsfirstlast 組合成一個陣列。

let ans2 = inventors.map(inventor => `${inventor.first} ${inventor.last}`);

map() 需要回傳一個值,他會透過函式內所回傳的值組合成一個新陣列。

  • 如果不回傳則是 undefined
  • 回傳數量等於原始陣列的長度

map()forEach() 差別:
forEach() 不會額外回傳值,只單純執行每個陣列內的物件或值。

如果要使用 forEach() 達成一樣功能,就要新增一個空陣列,並使用 push 將內容丟進空陣列。

let ans2 = [];

inventors.forEach(inventor =>
  ans2.push(`${inventor.first} ${inventor.last}`)
);

問題 3

Sort the inventors by birthdate, oldest to youngest.
inventor 依據生日由大至小排序。

let ans3 = inventors.sort((a, b) => a.year - b.year);

sort() 方法會原地(in place)對一個陣列的所有元素進行排序,並回傳此陣列。

排序不一定是穩定的,各家瀏覽器都不同,可以參考 從 Array 的 sort 方法,聊到各瀏覽器的實作,沒想到 Chrome 和FireFox 的排序如此不同 這篇文章。

問題 4

How many years did all the inventors live?
inventor 在世期間總和?

let total = inventors.reduce((total, inventor) => {
  return total + inventor.passed - inventor.year;
}, 0);

reduce() 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。

詳細可參考 JavaScript 中 reduce() 方法不完全指南

不用 reduce() 的作法:

let total = 0;
inventors.forEach(inventor => {
  total += inventor.passed - inventor.year;
});

問題 5

Sort the inventors by years lived.
inventor 依據年齡由大至小排序所有的。

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 網頁,列出所有包含 'de' 的路名。

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()方法用來判斷一個陣列是否包含一個指定的值,根據情況,如果包含則返回 true,否則返 false

問題 7

Sort the people alphabetically by last name.
peoplelastName 依據字母順序排序。

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() 方法使用指定的分隔符字符串將一個 String 對象分割成字串陣列,以將字符串分隔為子字符串,以確定每個拆分的位置。

問題 8

Sum up the instances of each of these.
分別計算 data 內每個種類的數量。

首先將累計器的預設值設為空物件 {}

let ans8 = data.reduce((obj, item) => {
  
}, {});

接著將物件建立出來,並加 1

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

因此需要加上判斷式:

if(!obj[item]){
  obj[item] = 0;
}

obj[item] 不存在就其建立並將值設為 0

這樣遇到重複的資料時,就不會又重設為 0,而會累加次數。

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
// }