주어진 단어 중 가장 짧은 단어 찾기

주어진 단어 중 가장 짧은 단어 찾기

이번 포스팅에서는 세 개의 단어가 함수에 인자로 주어졌을 때 글자수가 가장 짧은 단어를 찾는 방법에 대해 정리해 보았습니다.

// 문제

var output = findMinLengthOfThreeWords('a', 'be', 'see');
// ---> 함수 호출 시 숫자 1이 나와야 함.

먼저 for문으로 구하는 법에 대해 정리해 보았습니다.

function findMinLengthOfThreeWords(word1, word2, word3) {
  var newArr = [word1, word2, word3]; // 주어진 argument를 배열로 묶음.
  var minlength = word1.length; // newArr 배열의 첫 요소 글자수로 변수를 초기 설정
  for (var i = 0; i < newArr.length; i++) {
    // newArr 배열의 요소 수 만큼 반복문 설정
    if (newArr[i].length <= minlength) {
      minlength = newArr[i].length;
    } //현재 배열 요소의 글자수가 minlength보다 작거나 같으면 minlength를 대체함.
  }
  return minlength;
}

다음은 배열의 reduce() method를 사용해 해결하는 방법에 대해 정리해 보았습니다. reduce method는 각 배열의 요소마다 callback함수를 적용해 반환된 값(accumulator)을 다음 요소의 callback 함수에 적용하며, 최종적으로 하나의 도출된 값을 반환합니다.

Reduce Method 요약 - reduce는 배열 요소를 순차적으로 이동하며, 누적된 계산값과 함께 callback을 적용해 최종적으로 하나의 값을 도출합니다. - syntac: arr.reduce(callback [, intialValue]) - 배열의 모든 요소의 계산을 누적해 하나의 결과값을 도출할 때 용이함. - immutable

Callback 함수의 parameter reduce() method의 callback 함수는 아래와 같이 네 개의 parameter를 취할 수 있습니다. - accumulator    - reduce method의 initial value가 설정되어 있으면 accumulator는 initial value가 되고, currentValue는 배열의 첫 요소가 됩니다. 만약, initial value가 생략되었다면 accumulator는 배열의 첫 번째 값이 되고 current value는 배열의 두 번째 값이 됩니다. currentIndex - currentvalue - currentIndex    - 배열 내 현재 처리되고 있는 요소의 index 값입니다. method 작동 시 초기값이 주어진 경우는 0이되고, 초기값이 생략된 경우 1이 됩니다. - array    - reduce method가 작동하고 있는 배열.

Reduce Method 사용한 문제 풀이
function findMinLengthOfThreeWords(word1, word2, word3) {
  var newArr = [word1, word2, word3];
  var shortestWord = newArr.reduce(function(acc, cur) {
    if (acc.length <= cur.length) {
      return acc;
    }
  });
  return shortestWord;
}

var output = findMinLengthOfThreeWords('a', 'be', 'see'); // --> 'a'의 글자 수 1이 나옴
실수한 부분

저는 처음 reduce() method의 callback 함수 return 값으로 acc.length로 설정했다가 결과 값으로 undefined를 받았습니다.

이유는 callback함수에서 return값이 acc.length인 숫자가 되면, callback이 두번째 호출될 때 if 조건절에서 숫자.length <= cur.length를 비교하게 됩니다. 숫자에는 length 속성이 없기 때문에 if 조건절이 false가 되고, 두 번째 callback함수의 결과가 없는 undefined가 반환되었습니다.

실수한 부분인 두 번째 callback 실행 시 변수에 값을 대입해서 코드를 살펴보면,

function findMinLengthOfThreeWords(word1, word2, word3) {
    var newArr = [word1, word2, word3];
    var shortestWord = newArr.reduce(function(acc, cur) {
        if(1.length <= 'see') {  // if( undefined <= 'see')
            return acc.length
        }
    });
    return shortestWord;
};

위의 경우 두 번째 callback의 결과값이 없었기 때문에 최종적으로 undefined를 반환했습니다.

번외편: reduce 메서드의 초기값으로 빈 배열 이용하기

아래의 함수는 underscore.js 라이브러리의 uniq 함수와 동일한 기능을 구현한 것입니다. stackoverflow에 공유된 내용을, 참고차 정리해 봅니다.

참고로, 아래 함수는 배열에서 중복된 요소는 한 개씩만 남아있는 새로운 배열을 반환하는 함수입니다.

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

var uniq = names.reduce(function(a, b) {
    if(a.indexOf(b) < 0) {
        a.push(b);
        return a;
    },[]});

console.log(uniq); // ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]