[JS30] Day18: Tally String Times with Reduce
keywords: 時間
, time
, Array-like to Array
, dataset
, 秒數轉時分秒
今天會練習如何去把時間累加起來。
將時間累加
把 Array-like 的 Node 元素轉成 Array(Array-like to Array)
我們取得的 Node Element 它是 Array-like
的物件,而不是真的 Array,因此他沒有 Array.prototype.map
這個 function 可以使用,因此我們需要先把它轉成 Array:
方法一:使用 spread operator(...
)
const timeNodes = [...document.querySelectorAll('[data-time]')];
方法二:使用 Array.from()
// Array.from(<arrayLikeObject>)
const timeNodes = Array.from(document.querySelectorAll('[data-time]'));
把 data-set 的資料取出來
使用 Element.dataset.<attribute>
可以把 data-time
的值取出來。
陣列的解構賦值
在 ES6 中可以直接透過解構的方式賦值,像是下面這樣子:
let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3
如此變數 a = 1, b = 2, c = 3,這是最基本的陣列解構賦值方式。
因此,我們可以用這樣的寫法:
// 使用陣列的解構賦值
const [min, sec] = time
.split(':') // ['12', '39']
.map((str) => parseInt(str)); // 把字串轉成數值
陣列的解構賦值 @ PJCHENder HackMD
使用 Array.prototype.reduce
透過 Array.prototype.reduce( callback<accumulator, currentValue, currentIndex, array>, initialValue )
每次 return 的內容都會存到 accumulator 中,因此可以累加陣列裡的內容後回傳。
JavaScript 陣列 @ PJCHENder HackMD
程式碼
// 將 array-like 的 Node Element 轉成 Array
const timeNodes = [...document.querySelectorAll('[data-time]')];
const totalSeconds = timeNodes
.map((node) => node.dataset.time) // 把 nodeElement 的 data-time 取出來
.map((time) => {
// 把 time 全部變成秒數
const [min, sec] = time // 使用陣列的解構賦值
.split(':') // 得到字串['12', '39']
.map((str) => parseInt(str)); // 把字串轉成數值
return min * 60 + sec;
})
.reduce((totalSeconds, currentSeconds) => {
// 將所有的秒數累加
return totalSeconds + currentSeconds;
}, 0);
將秒數轉成「時:分:秒」
加總所有的秒數取得 totalSeconds
後,我們就可以將這個秒數在轉換為時分秒。
在這裡我們透過 Math.floor
達到無條件捨去的效果。而 totalSeconds % 3600
表示扣掉轉換完小時之後所剩下的秒數。
let hours = Math.floor(totalSeconds / 3600); // Math.floor 無條件捨去
let mins = Math.floor((totalSeconds % 3600) / 60);
let seconds = (totalSeconds % 3600) % 60;
console.log(hours, mins, seconds);