iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
自我挑戰組

JS30 學習日記系列 第 18

Day 18 - Tally String Times with Reduce

前言

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

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


本日目標

今天也是複習回,主要是拿來重新複習下 Array 的map()reduce()的用法。我們的最終目標是算出影片的長度總和並以時、分、秒呈現在 console裡。


解析程式碼

HTML 部分

以下是我們要用來計算影片總時數的清單,其中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 部分

一開始,我們宣告常數timeNodes用來放我們取得的所有清單項目(<li>~</li>),因為之後會用到 Array 的reduce()map(),這裡就順便把NodeListArray.from()轉換成 Array。

const timeNodes = Array.from(document.querySelectorAll('[data-time]'));

宣告常數seconds存入所有影片的秒數總和。

第一個map()幫我們取得個別影片時間所構成的陣列(分:秒)。
第二個map()幫我們把影片時間的分和秒切開(間隔符號:),第三個map()幫我們把陣列中的元素都轉換成浮點數,最後把影片的長度都換成秒(mins * 60 + secs)。

把影片長度都換成以秒為單位後,就可以用reduce()將它們加在一起囉!

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);
  • 第一次map()後產生的陣列

  • 第二、三次map()後產生的陣列

  • 所有影片長度的秒數總和

接下來,把得到的總秒數換成時、分、秒的形式就完成本日的目標囉!

let secondsLeft = seconds;
//Math.floor() 回傳小於等於所給數字的最大整數
const hours = Math.floor(secondsLeft / 3600);
secondsLeft = secondsLeft % 3600;

const mins = Math.floor(secondsLeft / 60);
secondsLeft = secondsLeft % 60;

console.log(hours, mins, secondsLeft);

補充資料:

Array.from()
parseFloat()
Array.prototype.map()
Array.prototype.reduce()
Math.floor()


上一篇
Day 17 - Sorting Band Names without articles
下一篇
Day 19 - Unreal Webcam Fun [更新]
系列文
JS30 學習日記30

尚未有邦友留言

立即登入留言