iT邦幫忙

2021 iThome 鐵人賽

DAY 4
1
自我挑戰組

JS30 學習日記系列 第 4

Day 4 - Array Cardio Day 1

前言

JS 30 是由加拿大的全端工程師 Wes Bos 免費提供的 JavaScript 簡單應用課程,課程主打 No FrameworksNo CompilersNo LibrariesNo Boilerplate 在30天的30部教學影片裡,建立30個JavaScript的有趣小東西。

另外,Wes Bos 也很無私地在 Github 上公開了所有 JS 30 課程的程式碼,有興趣的話可以去 fork 或下載。


本日目標

練習一些 Array 常用的方法,包括 filter()、sort()、map()、reduce()。

解析程式碼

JS 部分

前七個練習題要使用的資料如下:

/*JS*/
// 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 = [
    'Bernhard, Sandra', 'Bethea, Erin', 'Becker, Carl', 'Bentsen, Lloyd', 'Beckett, Samuel', 'Blake, William', 'Berger, Ric', 'Beddoes, Mick', 'Beethoven, Ludwig',
    'Belloc, Hilaire', 'Begin, Menachem', 'Bellow, Saul', 'Benchley, Robert', 'Blair, Robert', 'Benenson, Peter', 'Benjamin, Walter', 'Berlin, Irving',
    'Benn, Tony', 'Benson, Leana', 'Bent, Silas', 'Berle, Milton', 'Berry, Halle', 'Biko, Steve', 'Beck, Glenn', 'Bergman, Ingmar', 'Black, Elk', 'Berio, Luciano',
    'Berne, Eric', 'Berra, Yogi', 'Berry, Wendell', 'Bevan, Aneurin', 'Ben-Gurion, David', 'Bevel, Ken', 'Biden, Joseph', 'Bennington, Chester', 'Bierce, Ambrose',
    'Billings, Josh', 'Birrell, Augustine', 'Blair, Tony', 'Beecher, Henry', 'Biondo, Frank'
];

1. Filter the list of inventors for those who were born in the 1500's

Array.prototype.filter()
filter() 方法會透過指定的函式運算,決定保留哪些資料並形成一個新的陣列。

filter() 裡 return true 代表要保留該筆資料,除此之外的資料都會被捨棄,我們沒必要再寫 else 去 return false。

filter() 的詳細內容

以下我們透過 filter() 過濾"出生於16世紀的發明家"。

/*JS*/
const fifteen = inventors.filter(function(inventor){
    if(inventor.year >= 1500 && inventor.year < 1600){
        return true; //keep it in the new array
    }
})/*除了有回傳true之外的東西都會被丟掉,不必再用else return false*/

更簡潔的寫法:

console.table(),可以將 Array 以表格的形式呈現出來。

/*JS*/
const fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600));
console.table(fifteen);

2. Give us an array of the inventors first and last names

Array.prototype.map()
map() 方法會建立一個和原陣列長度相同的陣列,其內容為原陣列的每一個元素經由指定的函式運算後所回傳的結果之集合。

map() 的詳細內容

以下我們使用 map() 方法,將發明家的 first name 和 last name 結合在一起,形成一個新的陣列。

/*JS*/
const fullNames = inventors.map(inventor => `${inventor.first} ${inventor.last}`); /*Template literals*/
console.table(fullNames);

3. Sort the inventors by birthdate, oldest to youngest

Array.prototype.sort()
sort() 方法會對一個陣列中的所有元素進行排序,並回傳此陣列,預設是以字串的 Unicode 編碼進行排序。

我們也可以指定一個compareFunction,用自訂的排序規則為陣列進行排序。
compareFunction(a, b),回傳值小於0時,a 會被排在 b 的前面,反之若回傳值大於0時,a 會被排在 b 的後面。

sort() 的詳細內容

以下我們使用 sort(),將較早出生的發明家排在前面的位置。

const ordered = inventors.sort(function(a,b){
    if(a.year > b.year){
        return 1; /*a 往後排*/
    }else{
        return -1; /*a 往前排*/
    }
})

更簡潔的寫法:

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

4. How many years did all the inventors live all together?

Array.prototype.reduce()
reduce() 方法將一個累加器(accumulator)及陣列中每項元素傳入函式中進行運算,將陣列化為單一的值。

reduce() 的詳細內容

其中一種用法如下:

Array.reduce((accumulator,currentValue) => {
    return accumulator + currentValue;
 },initialValue); /*initialValue 是 accumulator 的初始值*/

另一種用法如下:

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

console.log(totalYears);

5. Sort the inventors by years lived

以下我們將這些發明家依照壽命的長短由大到小進行排序。
透過 passed - year,我們可以很簡單的算出每一位發明家的壽命。

const oldest = inventors.sort(function(a,b){
    const lastGuy = a.passed - a.year;
    const nextGuy = b.passed - b.year;
    return lastGuy > nextGuy ? -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 右鍵檢查進入 console 進行解題。

Node.textContent
可以取得節點或其後代的文字內容。

textContent 的詳細內容

Array.prototype.includes()
includes() 方法會判斷陣列是否包含特定的元素,並以此來回傳 truefalse

includes() 的詳細內容

Array.from()
從類陣列(array-like,例如: NodeList)或是可迭代(iterable)物件建立一個新的 Array 實體。

from() 的詳細內容

首先,我們取得包覆所有巴黎大道名稱的最上層 div 標籤(.mw-category)。接著,取得在其之下的所有連結(a)。最後,使用 map() 方法以所有連結的內部文字組成新陣列並透過 filter() 過濾出包含(include)'de'的所有大道名稱。

const category = document.querySelector('.mw-category');
const links = Array.from(category.querySelectorAll('a'));/*NodeList*/

const de = links.map(link => link.textContent).filter(streetName => streetName.includes('de'));

console.table(de);

7. Sort the people alphabetically by last name

String.prototype.split()
split()方法可以使用指定的分隔字元(separator)將一個String分割成串列。

split() 的詳細說明

以下用,(逗號和空格)作為分隔字元將 first name、last name 切開並放入一個陣列中,接下來就可以依照 aLast、bLast 的 Unicode 進行 last name 的排序(由小到大)。

const alpha = people.sort(function(lastOne,firstOne){
    const [aLast,aFirst] = lastOne.split(', ');
    const [bLast,bFirst] = firstOne.split(', ');
    return aLast > bLast ? 1 : -1;
});

另一種寫法:

const alpha = people.sort((lastOne,firstOne) => {
    const [aLast,aFirst] = lastOne.split(', ');
    const [bLast,bFirst] = firstOne.split(', ');
    return aLast > bLast ? 1 : -1;
});

8. Sum up the instances of each of these

資料內容:

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

一開始賦予累加器(obj)的初始值(initial value)為空物件({}),因為最初所有的 item 都不存在於 obj 中,所以透過 if 判斷當 obj[item] 不存在時,就建立 obj[item] 並賦予初始值0。其後就可正常將 item 持續累加至正確的交通工具分類中(obj[item]++)。

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

console.table(transportation);


上一篇
Day 3 - Playing with CSS
下一篇
Day 5 - Flex Panels Image Gallery
系列文
JS30 學習日記30

尚未有邦友留言

立即登入留言