Javascript_30_18

Derek·2021년 1월 4일
1

javascript_30

목록 보기
19/31
post-thumbnail

안녕하세요!

Derek 입니다 😄

넘나 피곤하네요 하루에 2개 포스팅이란..

이번 게시물인 Day 18 project도 17번째와 약간은 비슷한 느낌이에요.

눈에 보이는 작업은 아니였지만, 언제든지 유용할 것 같은 주제랍니다.

바로 시작해볼게요!




18. Adding up times with reduce

목표

HTMLdataset 에 있는 모든 시간을 더해서 시간 단위로 변환한다.

<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>
  ...

위와 같이 dataset 으로 시간이 있고, 총 58개의 시간 값을 더해서 시간단위로 변환해주는 작업이였습니다.


Derek 와 Wes Bos 구현코드

const timeNodes = [...document.querySelectorAll("[data-time]")];

const seconds = timeNodes.map(node => node.dataset.time).map(
  time => {
    const [mins, secs] = time.split(":").map(parseFloat); 
    return (mins * 60) + secs;
  }
).reduce((total, eachSeconds) => total + eachSeconds);


let convertingSeconds = seconds;

const hours = Math.floor(convertingSeconds / 3600);
convertingSeconds = convertingSeconds % 3600;

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

console.log(`${hours}:${mins}:${convertingSeconds}`);

let 으로 선언된 부분부터는 시간으로 표현하기 위한 작업이라, 그 위에 친구들을 중점으로 정리해보겠습니다.

01. dataset 속성 뽑기

먼저, HTML 구조가

<ul class="videos">
    <li data-time="5:43">
      Video 1
    </li>
    <li data-time="2:33">
      Video 2
  ...

이와 같기 때문에, data-time 속성을 뽑아야합니다. 이는 다음 두 가지 방법으로 가능해요.

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

그냥 간단하게

const timeNodes = document.querySelectorAll("[data-time]");

이렇게는 되지 않더라구요. 이는 timeNodes 가 배열이 아니라 NodeList 객체로 설정이 됨을 확인했습니다.

MDN 에 따르면,

Document 메소드 querySelectorAll() 는 지정된 셀렉터 그룹에 일치하는 다큐먼트의 엘리먼트 리스트를 나타내는 정적(살아 있지 않은) NodeList 를 반환합니다.

이미 정의에 NodeList 를 반환한다고 나와있군요! 따라서 배열로 만들어주는 작업이 당연히 필요했습니다.

이는 두가지 방법으로 가능해요. 여기보시면 배열로 만드는 많은 방법이 있는데, 여기서는 그 중에서도 spreadArray.from() 을 사용했습니다.

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

이를 수행하면, timeNodes 에는 <li> 배열이 58개가 들어가 있겠죠!

02. dataset.time 속성 모두 더해서 초단위로 표현하기

const seconds = timeNodes.map(node => node.dataset.time).map(
  time => {
    const [mins, secs] = time.split(":").map(parseFloat); 
    return (mins * 60) + secs;
  }
).reduce((total, eachSeconds) => total + eachSeconds);

추출한 timeNodes 의 원소 하나하나를 돌며 dataset.time 값을 추출하여 새로운 배열로 만듭니다. 그 배열을 또 map 함수를 써요!

time => {
    const [mins, secs] = time.split(":").map(parseFloat); 
    return (mins * 60) + secs;
  }

추출한 time 으로 새로운 배열을 만들었으니, 배열의 꼴은

["4:21", "3:22", ...]

이런꼴이였을 겁니다. 이 원소 하나하나를 이번에는 time 으로 지정하여, 초단위로 바꿔줘요.


처음에는

const [mins, secs] = time.split(":").map(parseFloat);

이 부분이 map 함수에 함수를 던져주면 알아서 하나? 싶었는데, MDN 에 예시부터가 이렇게 나와있더라구요. 원소 하나하나 돌면서 인자로 넘겨준 callback 함수를 수행하는 것으로 보입니다.

그렇다면 "3:19" 같은 time":"split 되고, 바로 그 찢어진 숫자 문자열을 parseFloat 로 숫자화하여 [mins, secs] 에 집어 넣습니다.


더 복잡해지는 것 같아요. 😥

그렇게 생긴 [mins, secs](mins * 60) + secs 를 리턴하게 하여 reduce 함수를 수행합니다.

const seconds = timeNodes.map(node => node.dataset.time).map(
  time => {
    const [mins, secs] = time.split(":").map(parseFloat); 
    return (mins * 60) + secs;
  }
).reduce((total, eachSeconds) => total + eachSeconds);

초기값이자 누적되는 변수인 total 에 현재 요소인 eachSeconds 가 하나하나 돌며 total 에 누적하여 더합니다.

그렇게 되면.. seconds 변수는.. 전체 합을 초단위로 가지고 있게 되는겁니다..!

03. 시간, 분, 초 단위로 변환

이제 seconds 에는 총 시간이 초단위로 저장되어 있습니다! 이 친구를 변환해야죠 :)

let convertingSeconds = seconds;

const hours = Math.floor(convertingSeconds / 3600);
convertingSeconds = convertingSeconds % 3600;

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

console.log(`${hours}:${mins}:${convertingSeconds}`);

계속 값이 바뀌므로 let 으로 선언해서 사용했습니다.

수학적인 지식을 가미하면 쉽게 이해가 가능해요.

  1. convertingSeconds3600 으로 나누고 나머지를 버림을 하면 시간 단위이고,
  2. 3600으로 mod 연산을 하여 convertingSeconds 로 집어 넣습니다.
  3. 이를 또 60으로 나누고 나머지를 버립니다. 그럼 그 값은 단위이며..
  4. 60으로 mod 연산한 값은 단위가 되는 겁니다!

말로 풀어쓰니.. 어려워 보이는데, 수학적으로 생각해보면 당연한 느낌..!




급하게 적느라 두서없이 적힌 것 같네요..! 그래도 map 함수와 reduce 함수가 이번 과제에서 관건인 것 같아서, 그 친구만 잘 눈여겨 본다면 좋을 것 같아요.

늦었네요..! 틀린내용이나 수정할 내용이 있다면 언제든지 피드백 부탁드립니다!

감사합니다!🤗

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글