Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 Ruby의 each_cons() 메서드 구현하기

Ruby의 each_cons() 메서드란?

Ruby의 each_cons()는 Enumerable(열거형)에 내장된 메서드로, 각 요소를 시작점으로 삼아 연속된 N개의 요소를 순회합니다. 블록이 주어지지 않으면 열거자(enumerator)를 반환합니다.

each_cons()의 JavaScript 버전

숫자 배열이 있다고 가정해 보겠습니다(여기서는 Ruby의 Enumerable에 해당하는 개념입니다). eachCons 함수는 배열의 각 요소에 대해 실행되며, 유일한 인자로 숫자 N(N은 배열 길이 이하)을 받습니다. 그리고 크기가 N인 하위 배열들로 이루어진 새로운 배열을 반환하는데, 각 하위 배열은 원본 배열의 요소를 하나씩 시작점으로 하여 생성됩니다.

예시를 통해 좀 더 명확하게 이해해 보겠습니다.

다음과 같은 배열이 있다고 가정해 봅시다.

const arr = [1, 2, 3, 4, 5];
console.log(arr.eachCons(2));

이 eachCons 호출은 다음과 같이 각각 2개의 요소를 가진 배열들의 배열을 만듭니다.

[[1, 2], [2, 3], [3, 4], [4, 5]]

하위 배열은 원본 배열의 각 요소마다, 더 이상 만들 수 없을 때까지 생성됩니다.

N의 값이 2 대신 3이었다면 결과는 다음과 같았을 것입니다.

[[1, 2, 3], [2, 3, 4], [3, 4, 5]]

마찬가지로 배열에 충분한 요소가 남아 있는 동안 모든 요소에 대해 하위 배열이 생성됩니다.

접근 방식

이 문제는 슬라이딩 윈도우(Sliding Window) 알고리즘을 사용하여 해결할 수 있습니다.

물론 최신 ES6 함수를 활용하면 두 줄 정도로도 해결할 수 있지만, 여기서 소개하는 방식이 훨씬 더 효율적입니다.

먼저 while 루프를 활용해 0번째부터 N번째 인덱스까지 초기 윈도우를 만듭니다. 그다음 for 루프를 사용하는데, 이 루프는 윈도우의 끝(end)이 원본 배열의 길이보다 작거나 같은 동안 계속 실행됩니다.

루프 내부에서는 윈도우의 안정성, 즉 윈도우의 길이가 N과 같은지 검사합니다. 윈도우가 안정적이라면 해당 윈도우(하위 배열)를 결과 배열에 삽입하고, 윈도우를 오른쪽으로 한 칸 민 뒤 축소합니다(start = end). 윈도우가 아직 불안정하다면 계속해서 요소를 추가합니다.

이 접근 방식의 코드는 다음과 같습니다.

예제

const arr = [1, 2, 3, 4, 5];
const eachCons = function(num){
   let res = [], temp = [];
   let start = 0, end = 0;
   while(end < num){
      temp.push(this[end++]);
   };
   for(; end <= this.length ;){
      if(temp.length === num){
         res.push(temp);
         start++;
         end = start;
         temp = [];
      }
      temp[end-start] = this[end];
      end++;
   }
   return res;
};
Array.prototype.eachCons = eachCons;
console.log([1, 2, 3, 4, 5].eachCons(1));
console.log([1, 2, 3, 4, 5].eachCons(2));
console.log([1, 2, 3, 4, 5].eachCons(3));
console.log([1, 2, 3, 4, 5].eachCons(4));

출력

콘솔 출력 결과는 다음과 같습니다.

[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ]
[ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 4, 5 ] ]
[ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ] ]
[ [ 1, 2, 3, 4 ], [ 2, 3, 4, 5 ] ]