본문으로 바로가기

flatten을 lazy evaluation으로 만들기 위해 아래와 같은 함수를 작성했습니다.

depth를 2 이상 가진 배열을 돌리면, 완전히 flatten되지 않습니다.

우선 위 함수 내부에 for...of 문이 중첩되어 들어가는 것이 가독성이 좋지 않게 보이므로 yield *를 활용하여 가볍게 만들겠습니다.

// iterable 안의 값도 iterable이면 펼쳐내는 작업. 단, depth가 1인 경우만 됨
const faltten = function* (iter) {
  for (const val of iter) {
    if (isIterable(val)) {
      for (const inner of val) {
        yield inner;
      }
    } else {
      yield val;
    }
  }
};

console.log([...faltten([1, 2, [3, 4]])]); // [1, 2, 3, 4]

 

yield* 란, iterable의 값들을 하나씩 펼쳐나가는 과정입니다.

// iterable인 a의 iterator의 value값을 for..of 문으로 뿌립니다.
for (const b of a) {
  yield b;
}

// 아래로 변경합니다.
yield* a;

 

결론적으론 아래와 같이 줄일 수 있습니다.

const flatten = function* (iter) {
  for (const val of iter) {
    if (isIterable(val)) yield* val;
    else yield val;
  }
};

 

 

아주 간단히 generator를 만들어보자면 아래와 같이 for...of 없이도 편리하게 iterator를 정의할 수 있습니다.

const testGen = function* (iter) {
  yield* iter;
};

const iter = testGen([1, 2, 3]);
console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.next()); // { value: 3, done: false }
console.log(iter.next()); // { value: undefined, done: true }

 

 

이제 depth가 2 이상인 배열도 flatten할 수 있도록 만들겠습니다. 이를 위해서 재귀적으로 실행하게 만들어야 합니다.

generator를 재귀적으로 실행할 수 있도록 함수형태로 만든 후에 yield* 에 값이 안인 함수를 배당하겠습니다.

L.deepFlatten = function* f(iter) {
  for (const val of iter) {
    if (isIterable(val)) yield* f(val);
    else yield val;
  }
};

console.log([...flatten([1, 2, [3, 4, [5, 6]]])]); // [1, 2, 3, 4, 5, 6]

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체