Day4 Array Cardio (1)

Demo

這周是針對陣列的操作做練習,所以沒有預覽圖!
主要看程式碼和console.log

關於陣列操作的教學我認為吳哲宇老師在Hahow上的教學(圖解)非常容易懂,
不過課程是要收費的,章節31-陣列的批次操作
課程連結

不是要幫他打廣告而是真心覺得解說得很好,偶而忘記還會回去複習一下XD

先來看看我們取得的資料有哪些:

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

我們有兩筆資料,第一筆看起來是一些偉人吧,姓名和生平,第二筆則是一堆名稱。

filter()

Filter the list of inventors for those who were born in the 1500’s。
我們要去取得1500~1600年代出生的人

關鍵:filter() 詳細介紹:MDN

白話解釋:從陣列裡一筆一筆資料去過濾(篩選),選出符合條件的那筆資料,再回傳產生一個新的陣列

1
2
3
4
let question_1 = inventors.filter( item => {
item.year >= 1500 && item.year < 1600
})
console.log(question_1)

console.table()可以印出表格,滿酷的

map()

Give us an array of the inventors’ first and last names
我們要做一筆資料,只含他們的姓名就好

關鍵:map() 詳細介紹:MDN

白話解釋:從陣列裡一筆一筆資料去抓出來去做一件事(涵式),再把結果放到(產生))一個新的陣列

1
2
3
4
5
6
7
let question_2 = inventors.map( item => {
return {
first: item.first,
last: item.last
}
})
console.log(question_2)

這裡我們return的是物件,因為需要有first和last的值

產生的結果:

sort()

Sort the inventors by birthdate, oldest to youngest
由老到年輕排列

關鍵:sort() 詳細介紹:MDN

  • 若 sort(a, b) 的回傳值小於 0,則會把 a 排在小於 b 之索引的位置,即 a 排在 b 前面

  • 若 sort(a, b) 的回傳值大於 0,則會把 b 排在小於 a 之索引的位置,即 b 排在 a 前面

如果我們是為了比較簡單的數字,可以利用 a 減 b。(由小到大)

1
2
3
4
inventors.sort((a,b)=>{
return a.year - b.year
})
console.log(inventors)

反之降序

1
2
3
4
inventors.sort((a,b)=>{
return b.year - a.year
})
console.log(inventors)

寫法二:

1
2
3
4
5
6
7
inventors.sort((a,b)=>{
if(a<b){
return -1//由小到大
}else(a>b){
return 1 //由大到小
}
})

sort我認為是陣列操作裡面最難理解的,實際運作原理待研究…。

reduce()

How many years did all the inventors live?
所有人的年紀加總

關鍵:reduce() 詳細介紹:MDN

白話解釋:我們會有一個暫存值,進入陣列去跟每個值做運算,最後回傳這個暫存值

1
2
3
4
5
let question_4 = inventors.reduce(function(temp,item){
return temp+(item.passed-item.year)
},0)
//item.passed-item.year = 年齡
console.log(question_4)
  • temp : 就是reduce提供我們可以自訂名稱的暫存值
  • item : inventors陣列裡面的每個物件。
  • 0 : 最後面的0就是預設值。

如果我們用forEach做(有點像是forEach結合我們要的變數?)

1
2
3
4
5
let temp = 0
inventors.forEach(item=>{
temp += (item.passed-item.year)
})
console.log(temp)

sort()

Sort the inventors by years lived
根據這些發明家的年紀做排序

應該就是第三題的延伸,先算出年紀再做排序。

1
2
3
4
inventors.sort((a,b)=>{
return (a.passed-a.year) -(b.passed-b.year)
})
console.log(inventors)

Array.from()/.map()/.includes()

create a list of Boulevards in Paris that contain ‘de’ anywhere in the name
這題好像叫我們直接到這個網站去抓名字裡面含有‘de’的清單。

一步一步取得對象!

1
let peoples = document.querySelectorAll('.mw-category-group a');

注意:我們透過document.querySelectorAll()取得的這peoples,它是一個叫做NodeList的類似陣列的東西,他並不具陣列的所有功能

NodeList不是陣列!這邊有更多介紹

接著透過Array.from()產生我們要的陣列:

1
let array = Array.from(peoples)

Array.from() 方法會從類陣列(array-like)或是可迭代(iterable)物件建立一個新的 Array 實體。這邊有更多介紹

結果:

有了這筆資料後,我們再透過map()(或forEach)的方法取出所有姓名。

1
array.map(item => {return item.innerHTML})

結果:

最後,我們去過濾/篩選出名字中含有’de’的人

1
2
3
let result = newList.filter(name=>{
return name.includes('de')
})

結果:

補充:includes()方法會判斷陣列是否包含特定的元素,並以此來回傳 true 或 false。

.map()/.sort()/.split()

Sort the people alphabetically by last name
透過last name排序長度去排序people這筆陣列。

people這筆陣列中並沒有分出last name或first name,所以我們要透過split()去切割字串

1
2
3
4
let newPeople = people.map(name=>{
return name.split(', ')//從逗號和空白這邊切開
})
console.log(newPeople)

split(),這裡有詳細介紹

結果:原本的每一筆姓名都被切開成兩個了。

預設的排序順序是根據字串的 Unicode 編碼位置(code points)而定。

1
2
3
4
5
6
7
newPeople.sort((a,b)=>{
if(a[1]>b[1]){
return 1;
}else{
return -1
}
})

結果:可以看到LastName就從字母A開始排序了。

寫法二:透過map去產生帶有物件(lastName,lastName)的陣列後再去排序比較易讀一點。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let newPeople = people.map(name=>{
const temp = name.split(', ')//一樣先拆解
return {//再回傳物件
firstName: temp[0],
lastName: temp[1]
}
})
newPeople.sort((a,b)=>{
if(a.lastName>b.lastName){
return 1
}else{
return -1
}
})

這題是按照自己意思去寫的,原始範例寫的排列方式和結果和我想像的按字母排序不太一樣…

.reduce() (obj)

Sum up the instances of each of these
以下陣列每個項目各有幾個,做統計

1
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];

所以最後得到的結果需要是一個物件類似這樣:

1
2
3
4
5
6
let 統計結果:{
汽車:2,
卡車:3,
..
...
}

複習第四題的reduce

白話解釋:我們會有一個暫存值,進入陣列去跟每個值做運算,最後回傳這個暫存值

所以,這次我們把暫存值設定成一個物件,初始值則是物件中的屬性。
結構:

1
2
3
4
5
let result = data.reduce(function(object, item){
//..
//...
return obj
},{})

首先先把物件的樣子先做出來

1
2
3
4
let result = data.reduce(function(obj,item){
obj[item] = 0
return obj
},{})

有點像我們要的結果了…有五種交通方式

但是我們需要的是正確數量,一開始可能直覺的寫法是後面再加上obj[item]++

1
2
obj[item] = 0
obj[item]++

但這樣會不斷地把item變成0然後再+1變成0再+1….,永遠只會有1而已
所以我們要怎麼讓obj[item] = 0執行(定義)一次就好?

加入判斷:因為只有一開始obj[item]會是空值,後面就會++了,所以他只會跑一次。

1
2
3
4
5
6
7
let result = data.reduce(function(obj,item){
if(!obj[item]){
obj[item] = 0
}
obj[item]++
return obj
},{})

運作邏輯大概是像這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//round1 第1個car來了
result = {
'car'= 0 //car第一次進判斷
}
//round2
result = {
'car'= 1
}
//round3 第2個car來了
result = {
'car'= 2 //不進判斷了,直接第二次遞增
}
//round4 第1個truck來了
result = {
'car'= 2,
'truck'= 0, //truck第一次進判斷
}
//round4
result = {
'car'= 2,
'truck'= 1, //truck第一次遞增
}
//依此類推

不得不說,如果沒看答案我應該永遠想不到有這種方式…陣列的操作一直是我不熟悉的技術之一,但透過這個主題練習真的學到很多!後續可能還會一直翻回來做複習。

不負責任聲明ಥ◡ಥ:
純屬個人筆記,每個範例都有不同的寫法,還有很多細節可以加入,甚至可能有看不到的bug,有任何問題都歡迎提出一起研究哦,我會很感謝您的!- 2018.08.10

0%