github-blog.png


✍️ Today I Learned

프로그래머스 그림 확대 알고리즘 문제 풀이 과정 중 평소에 사용해보지 않은 Array 인스턴스의 메서드 중 하나인 flatMap()을 사용해서 풀이하며 느낀점을 간단히 포스팅으로 남기려한다.



1. 문제


문제 설명

  • 직사각형 형태의 그림 파일이 있고, 이 그림 파일은 1 × 1 크기의 정사각형 크기의 픽셀로 이루어져 있습니다. 이 그림 파일을 나타낸 문자열 배열 picture과 정수 k가 매개변수로 주어질 때, 이 그림 파일을 가로 세로로 k배 늘린 그림 파일을 나타내도록 문자열 배열을 return 하는 solution 함수를 작성해 주세요.

제한사항

  • 1 ≤ picture의 길이 ≤ 20
  • 1 ≤ picture의 원소의 길이 ≤ 20
  • 모든 picture의 원소의 길이는 같습니다.
  • picture의 원소는 ’.’과 ‘x’로 이루어져 있습니다.
  • 1 ≤ k ≤ 10

입출력 예

  • picture k result
    [“.xx…xx.”, “x..x.x..x”, “x…x…x”, “.x…x.”, “..x…x..”, “…x.x…”, “…x…“] 2 [“..xxxx…xxxx..”, “..xxxx…xxxx..”, “xx…xx..xx…xx”, “xx…xx..xx…xx”, “xx…xx…xx”, “xx…xx…xx”, “..xx…xx..”, “..xx…xx..”, “…xx…xx…”, “…xx…xx…”, “…xx..xx…”, “…xx..xx…”, “…xx…”, “…xx…“]
    [“x.x”, “.x.”, “x.x”] 3 [“xxx…xxx”, “xxx…xxx”, “xxx…xxx”, “…xxx…”, “…xxx…”, “…xxx…”, “xxx…xxx”, “xxx…xxx”, “xxx…xxx”]


2. 처음 풀이한 해결 방법


알고리즘 난이도 자체는 “기초”에 해당할 만큼 쉽기에 따로 풀이과정을 주석 외에 따로 설명하진 않겠다.

function solution(picture, k) {
  const result = [];  // 결과값을 담을 배열을 선언
  
  picture.forEach((row) => {
    // picture 배열을 순회하며 row값(문자열)을 k만큼 확장한다. => 가로 확대
    const expandedRow = [...row].map(char => char.repeat(k)).join('');

    // 확장한 row를 결과값에 k번 더한다. => 세로 확대
    for (let i = 0; i < k; i++) {
      result.push(expandedRow);
    }
  });
  
  return result;
}


좀더 간결하게 구현할 수 있지 않을까란 생각으로 map() 메서드를 사용하는 방법으로 변경해보았다.

function solution(picture, k) {
  const result = picture
    .map((row) => 
      Array(k).fill([...row].map(char => char.repeat(k)).join(''))
    )
    .flat();

  return result;
}

별도의 반환값이 없는 forEach()for 문법을 사용하려면 변수를 미리 선언 후 push 등을 통해 제어해야하지만 map() 메서드를 활용하면 반환값을 적절히 제어할 수 있으므로 코드를 간결히 작성할 수 있었다.



3. flatMap() 메서드를 활용한 해결 방법


사실 이번 포스팅을 남긴건 flatMap() 때문이다. 이런 메서드가 있다는 사실을 처음 알았다. 🥲

요구하는 결과값이 1차원 배열일 때 map() 메서드의 콜백 반환값이 배열인 경우에는 falt() 메서드로 적절히 평탄화해서 콜백 함수의 리턴값으로 반환하곤했는데 그걸 한번에 해결해주는 메서드가 있었다는걸 처음 알게되었다.

ECMAScript 2019(ES10)에 새롭게 추가되었다 한다. (무려 5년전..🥲)


메서드의 동작 원리는 간단하다.

  • map() 뒤에 깊이 1의 flat()을 붙이는 것.
function solution(picture, k) {
  return picture.flatMap((row) => 
    Array(k).fill([...row].map(char => char.repeat(k)).join(''))
  );
}

map()flat() 메서드를 따로 호출하는 것보다는 보기에 조금 더 직관적이지 않나 싶다.



🤔 Understanding

2009년에 ES5가 등장하고 2015년에 ES6가 등장하며 큰 변화가 겪은 이후 ECMA에서는 매년 새로운 JS 표준을 발표하고 있다. 표준 문법안을 읽기만하고 써버릇하며 체득하지 않으니 이렇게 쉽게 잊어버리는듯 하다. 😮‍💨

앞으로는 매년 나오는 새로운 문법에 익숙해지기 위해서 억지로라도 조금씩 활용해보고 포스팅으로 남겨야겠다.