[JavaScript 30]Day18-Tally String Times with Reduce

Ivy Ho
IvyCodeFive
Published in
6 min readAug 20, 2022

今天要練習的是,如何將 Playlists 內所有格式為「00:00」的影片時間加總,計算出總共的時間為幾時幾分幾秒。

課程中的示意圖,非練習範例畫面

學習重點

  • NodeList 轉 Array : [… ]Array.from()
  • 資料處理,組成新陣列 : .map()
  • 分割字串 : .split()
  • 加總 : .reduce()
  • 無條件捨去小數,取整數 : Math.floor()
  • 餘數運算子: "%"

觀察範例檔案初始狀態

HTML

範例中預設有一個 videos 列表,裡面的<li>項目都有 data-time 屬性,值為每段影片的時間。

<ul class="videos">
<li data-time="5:43">
Video 1
</li>
<li data-time="2:33">
Video 2
</li>
<li data-time="3:45">
Video 3
</li>
<li data-time="0:47">
Video 4
</li>
<li data-time="5:21">
Video 5
</li>
.
.
.
</ul>

(最後完成的完整 JS 程式碼,以及檔案下載、課程連結,將放在最下方)

步驟拆解

  1. 取得 NodeList,並轉成 Array
  2. 取得每個節點內的 data-time 屬性值
  3. 取得分、秒,轉成數字,並計算成總秒數
  4. 將所有影片的秒數加總
  5. 將總秒數換算成 「時:分:秒」 格式

1. 取得 NodeList,並轉成 Array

  • 抓取含有 data-time 屬性的所有節點,querySelectorAll 所取得的會是一個 NodeList。
  • 利用 Array.from()[… ] 方法將 NodeList 轉為陣列。

2. 取得每個節點內的 data-time 屬性值

  • 利用 .dataset.time 取得屬性值。
  • 利用 .map() 方法將所有 data-time 屬性值組成一個新的陣列。

利用 console.log 查看目前取得的資料狀態 :

3. 取得分、秒,轉成數字,並計算成總秒數

  • 一樣使用 .map() 方法。
  • 利用 .split(':') 來分割冒號兩邊的數字(字串)。
  • .map() 內可以直接呼叫 parseFloat 方法,便可將字串轉為數字。
  • 利用 ES6 解構附值寫法分別取得 分(mins), 秒(secs)。
  • 在下方進行運算,將分鐘換算成秒數後加總,並作為返回值。

利用 console.log 查看目前取得的資料狀態 :

會得到每一個影片的總秒數,所組成的陣列

4. 將所有影片的秒數加總

  • 利用 .reduce 方法將所有陣列內的秒數加總

利用 console.log 查看是否得到總秒數 :

5. 將總秒數換算成 「時:分:秒」 格式

  • 將秒數除以 3600,換算成小時。利用 Math.floor() 取整數。
  • 餘數運算子% 可取得剩餘秒數。
  • 分鐘數的算法與上述相似。

最後就能得到所有影片的總時間,為幾時幾分幾秒。

console.log 查看剛剛計算出來的 hours, mins, secondsLeft :

今天的練習就到這邊結束囉~

完整 JS 程式碼

const timeNodes = Array.from(document.querySelectorAll('[data-time]'));const seconds = timeNodes
.map(node => node.dataset.time)
.map(timeCode => {
const [mins, secs] = timeCode.split(':').map(parseFloat);
return (mins * 60) + secs;
})
.reduce((total, vidSeconds) => total + vidSeconds);
let secondsLeft = seconds;
const hours = Math.floor(secondsLeft / 3600);
secondsLeft = secondsLeft % 3600;
const mins = Math.floor(secondsLeft / 60);
secondsLeft = secondsLeft % 60;
console.log(hours, mins, secondsLeft);

--

--

Ivy Ho
IvyCodeFive

"You don't have to be great to start, but you have to start to be great."