@lemon2003の技術ブログ

tl;dr

  • javascript には イテレーター という仕組みがある。
  • より簡単にイテレータを作る手段として ジェネレーター関数がある。
  • それを使えば、数列などを一個ずつ取り出す関数を簡単に実装することができる。

ジェネレータの書き方

// function* でジェネレータ関数を作成。  
function* iterator() {  
  let i = 0;  
  yield i;  

  for(let i = 0; i < 5; i++) yield ++a;  
}  

// ジェネレータ作成  
let generator = iterator();  

// .next() で次の yield まで実行  
// result.done が true になるまで  
do {  
  const result = generator.next();  
  console.log(result.value); //> 0 1 2 3 4  
} while (!result.done)  

いろいろなgenerator作ってみた。

等差数列

start: スタートの数値
end: 上限値 (それ自身を含まない)
step: 増加量

param
start 0 0, 1, 2, 3, ...
end Infinity
step 1
start 5 5, 13, 21, 29
end 30
step 8
start 0 0, -5, -10, -15, ...
end -Infinity
step -5
コード
function* 等差数列(start = 0, end = Infinity, step = 1){  
  if(step < 0) end = - Infinity;  

  for(let i = start; i < end; i += step){  
    yield i;  
  }  
}  

See the Pen 等差数列 by lemon2003 (@lemon2003) on CodePen.

三角数

1 3 6 10 15
+2 +3 +4 +5
コード
function* 三角数(){  
    let current = 0;  

    let i = 1;  
    while(true){  
      current += i++;  
      yield current;  
    }  
  }  

See the Pen 三角数 by lemon2003 (@lemon2003) on CodePen.

等比数列

n: 前後の比

param
n 2 1, 2, 4, 8, ...
n 3 1, 3, 9, 27, ...
n 10 1, 10, 100, 1000, ...
コード
function* 等比数列(n = 2){  
    let current = 1;  
    yield current;  

    while(true){  
      current *= n;  
      yield current;  
    }  
  }  

See the Pen 等比数列 by lemon2003 (@lemon2003) on CodePen.

階乗

0! 1! 2! 3! 4! 5!
1 1 2 6 24 120
*2 *3 *4 *5
コード
function* 階乗(){  
    let current = 1;  
    yield current;  

    let i = 1;  
    while(true){  
      current *= i++;  
      yield current;  
    }  
  }  

See the Pen 階乗 by lemon2003 (@lemon2003) on CodePen.

Nフィボナッチ数列

n: 何個前までの値を参照するか

param
n 2 0, 1, 1, 2, 3, 5, 8, 13, ...
n 3 0, 0, 1, 1, 2, 4, 6, 12, ...
n 4 0, 0, 0, 1, 1, 2, 4, 8, ...
コード
function* Nフィボナッチ数列(n = 2){  
    let list = [];  

    for(let i = 0, l = n - 1; i < l; i++){  
      list.push(0);  
      yield 0;  
    }  

    list.push(1);  
    yield 1;  

    while (true) {  
      const current = list.slice(list.length - n, list.length).reduce((prev, current) => prev + current);  
      yield current;  
      list.push(current);  
    }  
  }  

See the Pen Nフィボナッチ数列 by lemon2003 (@lemon2003) on CodePen.

見て言って数列

1: One one
11: Two one
21: One two, One one
1211: One one, One two, Two one
111221: Three one, Two two, One one
312211: One three, One one, Two two, Two one
13112221: One one, One three, Two one, Three two, One one
1113213211: Three one, One three, One two, One one, One three, One two, Two One
31131211131221: One three, Two one, One three, One one, One two, Three one, One three, One one, Two two, One one
13211311123113112211: One one, One three, One two, Two one, One three, Three one, One two, One three, Two one, One three, Two one, Two two, Two one

コード
function* 見て言って数列(){  
    let current = "1";  
    yield current;  

    while(true){  
      current = current.replace(/([0-9])\1*/g, (match, p1) => match.length + p1);  
      yield current;  
    }  
  }  

See the Pen 見て言って数列 by lemon2003 (@lemon2003) on CodePen.

終わりに

使うタイミングが頻繁にあるかどうかで言うと微妙ですが、知っておいて損はないと思います。

この記事へのコメント

まだコメントはありません