Edited at

ジェネレーターでいろいろな数列を発生させてみる。


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, \cdots $

end
Infinity

step
1

start
5
$ 5, 13, 21, 29 $

end
30

step
8

start
0
$ 0, -5, -10, -15, \cdots $

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, \cdots $

n
3
$ 1, 3, 9, 27, \cdots $

n
10
$ 1, 10, 100, 1000, \cdots $

コード

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, \cdots $

n
3
$ 0, 0, 1, 1, 2, 4, 6, 12, \cdots $

n
4
$ 0, 0, 0, 1, 1, 2, 4, 8, \cdots $

コード

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.


終わりに

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