JS30 Day04
對 JS 新手來說,這堂課非常重要。學會 Array 的各種方法,就可以解決大部分的問題!


Array Cardio Day 1

完成目標

今日的主題與呈現漂亮的畫面無關,而是學習 JavaScript 中常見的 Array 方法。




index-START.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Array Cardio 💪</title>
</head>
<body>
<p><em>Psst: have a look at the JavaScript Console</em> 💁</p>
<script>
// Get your shorts on - this is an array workout!
// ## Array Cardio Day 1

// Some data we can work with

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"
];

// Array.prototype.filter()
// 1. Filter the list of inventors for those who were born in the 1500's

// Array.prototype.map()
// 2. Give us an array of the inventors' first and last names

// Array.prototype.sort()
// 3. Sort the inventors by birthdate, oldest to youngest

// Array.prototype.reduce()
// 4. How many years did all the inventors live?

// 5. Sort the inventors by years lived

// 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name
// https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris

// 7. sort Exercise
// Sort the people alphabetically by last name

// 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"
];
</script>
</body>
</html>

index-FINISHED.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Array Cardio 💪</title>
</head>
<body>
<p><em>Psst: have a look at the JavaScript Console</em> 💁</p>
<script>
// Get your shorts on - this is an array workout!
// ## Array Cardio Day 1

// Some data we can work with

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"
];

// Array.prototype.filter()
// 1. Filter the list of inventors for those who were born in the 1500's
const fifteen = inventors.filter(
inventor => inventor.year >= 1500 && inventor.year < 1600
);

console.table(fifteen);

// Array.prototype.map()
// 2. Give us an array of the inventor first and last names
const fullNames = inventors.map(
inventor => `${inventor.first} ${inventor.last}`
);
console.log(fullNames);

// Array.prototype.sort()
// 3. Sort the inventors by birthdate, oldest to youngest
// const ordered = inventors.sort(function(a, b) {
// if(a.year > b.year) {
// return 1;
// } else {
// return -1;
// }
// });

const ordered = inventors.sort((a, b) => (a.year > b.year ? 1 : -1));
console.table(ordered);

// Array.prototype.reduce()
// 4. How many years did all the inventors live?
const totalYears = inventors.reduce((total, inventor) => {
return total + (inventor.passed - inventor.year);
}, 0);

console.log(totalYears);

// 5. Sort the inventors by years lived
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);

// 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name
// https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris

// 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'));

// 7. sort Exercise
// Sort the people alphabetically by last name
const alpha = people.sort((lastOne, nextOne) => {
const [aLast, aFirst] = lastOne.split(", ");
const [bLast, bFirst] = nextOne.split(", ");
return aLast > bLast ? 1 : -1;
});
console.log(alpha);

// 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",
"pogostick"
];

const transportation = data.reduce(function(obj, item) {
if (!obj[item]) {
obj[item] = 0;
}
obj[item]++;
return obj;
}, {});

console.log(transportation);
</script>
</body>
</html>



學習筆記


★ console.table()

console.table() 可以使資料以表格的方式呈現。

範例:

假設有個陣列 people

1
2
3
4
5
let people = [
{ name: "Chai", favorites: "dessert" },
{ name: "Jay", favorites: "novel" },
{ name: "Kawa", favorites: "baseball" }
];
  • 使用 console.log(people) 輸出,會得到這樣的樹狀結構


    console.log(people)
  • 使用 console.table(people) 輸出,則會得到整齊的表格


    console.table(people)

*除了 console.log() 以及 console.table() 以外,還有許多 console 方法,可以參考:https://developer.mozilla.org/en-US/docs/Web/API/Console

★ Array.from()

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

範例:

1
2
3
4
5
6
console.log(Array.from("Chai"));

// ["C", "h", "a", "i"]

Array.from([1, 2, 3], x => x + x);
// [2, 4, 6]


接著是課程中使用的陣列方法們


★ Array.filter()

filter() 方法會建立一個新陣列,新陣列是經指定之函式運算後,由原陣列中通過該函式檢驗之元素所構成的。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
const books = [
"Three Act Tragedy",
"The A.B.C. Murders",
"Cards on the Table",
"And Then There Were None"
];

// 篩選出第一個字為 'T' 的書
const result = books.filter(book => book.charAt(0) === "T");

console.log(result);
// Array ["Three Act Tragedy", "The A.B.C. Murders"]

★ Array.map()

map() 方法會建立一個新陣列,其內容為原陣列的每一個元素經由回呼函式運算後所回傳的結果之集合。

範例:

1
2
3
4
5
6
7
const array1 = ["Chai", "Jay", "Kawa", "Annie"];

// 傳給 map 一個函式
const map1 = array1.map(x => `super cute ${x}`);

console.log(map1);
// Array ["super cute Chai", "super cute Jay", "super cute Kawa", "super cute Annie"]

★ Array.sort()

sort() 方法會對陣列元素進行排序,並回傳此陣列。

語法:arr.sort([compareFunction])

compareFunction 為自定義的排序函式。假如省略此參數,陣列將根據各個元素轉為字串後的每一個字元之 Unicode 編碼位置值進行排序。

*注意:此發法會原地(in place)進行排序,會改變原陣列,並不是原陣列的拷貝。

範例:

1
2
3
4
5
6
7
8
9
10
11
const names = ["Chai", "Jay", "Kawa", "Annie"];
names.sort();
console.log(names);

// Array ["Annie", "Chai", "Jay", "Kawa"]

const array1 = [1, 40, 3, 21, 1000000];
array1.sort();
console.log(array1);

// Array [1, 1000000, 21, 3, 40]

如果有傳 compareFunction ,陣列元素們將根據比較函式之回傳值來排序。如果 ab 為被比較之兩元素,則:

  • compareFunction(a, b) 的回傳值小於 0,則會把 a 排在小於 b 之索引的位置,即 a 排在 b 前面。
  • compareFunction(a, b) 回傳 0,則 ab 皆不會改變彼此的順序,但會與其他全部的元素比較來排序。備註:ECMAscript 標準並不保證這個行為,因此不是所有瀏覽器(如 Mozilla 版本在 2003 以前)都遵守此行為。
  • compareFunction(a, b) 的回傳值大於 0,則會把 b 排在小於 a 之索引的位置,即 b 排在 a 前面。
  • compareFunction(a, b) 在給予一組特定元素 a 及 b 為此函數之兩引數時必須總是回傳相同的值。若回傳值不一致,排序順序則為 undefined。

比較函式會是以下形式:

1
2
3
4
5
6
7
8
9
10
function compare(a, b) {
if (在某排序標準下 a 小於 b) {
return -1;
}
if (在某排序標準下 a 大於 b) {
return 1;
}
// a 必須等於 b
return 0;
}

為了比較數字而不是字串,比較函式可以僅僅利用 ab。以下函式將會升冪排序陣列:

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

範例:

1
2
3
4
5
6
7
let numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);

// [1, 2, 3, 4, 5]

★ Array.reduce()

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

語法: arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)

*注意:假如 initialValue 未被提供,reduce() 將會跳過第一個陣列索引,從陣列索引 1 開始執行回呼函式。若有提供 initialValue,則會由陣列索引 0 開始執行。

範例:

1
2
3
4
5
6
7
8
9
const array1 = [1, 2, 3, 4, 5];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

console.log(array1.reduce(reducer));
// 15

// 給初始值 5 ,所以為 5 + 1 + 2 + 3 + 4 + 5
console.log(array1.reduce(reducer, 5));
// 20