LoginSignup
0
1

More than 5 years have passed since last update.

要素の組み合わせをすべて列挙する。

Posted at

はじめに

  • パラメータの組み合わせなどを確認するときに条件の組み合わせをすべて列挙したくなるときありませんか?
  • p1は[1,2],p2は[A,B]の値を取る時に、
    1. p1=1&p2=A
    2. p1=1&p2=B
    3. p1=2&p2=A
    4. p1=2&p2=B
  • のような組み合わせを作りたいということです。
for (p1) {
    for (p2) {
        for (p3) {
            ///
        }
    }
}
  • ってやれば出来るんですが、階層を全部入れ子にするのは面倒くさいですね。

作ってみました。

プログラム

enumerate.js
"use strict";

function enumerate(parameters) {
        var enumrate_array = []; //答え
        // 総件数を計算
        var total = parameters.reduce(function(p,c){ return p * c.values.length; },1);
        // 組み合わせを作成する
        var count = 1;
        for (var i = 0; i < parameters.length; i++) {
                var values = parameters[i].values;
                count = count * values.length;
                var div = total / count;
                var idx = 0;
                do {
                        for (var m = 0; m < values.length; m++) {
                                for (var k = 0; k < div; k++) {
                                        if (enumrate_array[idx] === undefined) {
                                                enumrate_array[idx] = [];
                                        }
                                        enumrate_array[idx].push({
                                                'key': parameters[i].key,
                                                'value': parameters[i].values[m]
                                        });
                                        ++idx;
                                }
                        }
                } while (idx < total);
        }
        return enumrate_array;
}

var param = [
        {'key': 'p1','values': [1, 2, 3]}, //数字でも
        {'key': 'p2','values': ['A', 'B', 'C']}, //文字列でも
        {'key': 'p3','values': [{'name': 'john'}, {'name': 'kate'}, {'name': 'fox'}]} //オブジェクトでも
];

// 独立変数p1,p2,p3なので 3 × 3 × 3 = 27通りの組み合わせができます。
//console.log(JSON.stringify(enumerate(param), undefined, 4));

var e = enumerate(param);
console.log('enumerate size : ' + e.length);
var no = 1;
e.forEach(function(p){
    var row = [];
    p.forEach(function(v){
        row.push(v.key + '=' + JSON.stringify(v.value));
    });
    console.log(no +"\t" + row.join("\t"));
    ++no;
});

実行

  • node.jsで実行してみてください。
node.js
% node enumerate.js > enumerate.txt

結果

enumerate size : 27
1   p1=1    p2="A"  p3={"name":"john"}
2   p1=1    p2="A"  p3={"name":"kate"}
3   p1=1    p2="A"  p3={"name":"fox"}
4   p1=1    p2="B"  p3={"name":"john"}
5   p1=1    p2="B"  p3={"name":"kate"}
6   p1=1    p2="B"  p3={"name":"fox"}
7   p1=1    p2="C"  p3={"name":"john"}
8   p1=1    p2="C"  p3={"name":"kate"}
9   p1=1    p2="C"  p3={"name":"fox"}
10  p1=2    p2="A"  p3={"name":"john"}
11  p1=2    p2="A"  p3={"name":"kate"}
12  p1=2    p2="A"  p3={"name":"fox"}
13  p1=2    p2="B"  p3={"name":"john"}
14  p1=2    p2="B"  p3={"name":"kate"}
15  p1=2    p2="B"  p3={"name":"fox"}
16  p1=2    p2="C"  p3={"name":"john"}
17  p1=2    p2="C"  p3={"name":"kate"}
18  p1=2    p2="C"  p3={"name":"fox"}
19  p1=3    p2="A"  p3={"name":"john"}
20  p1=3    p2="A"  p3={"name":"kate"}
21  p1=3    p2="A"  p3={"name":"fox"}
22  p1=3    p2="B"  p3={"name":"john"}
23  p1=3    p2="B"  p3={"name":"kate"}
24  p1=3    p2="B"  p3={"name":"fox"}
25  p1=3    p2="C"  p3={"name":"john"}
26  p1=3    p2="C"  p3={"name":"kate"}
27  p1=3    p2="C"  p3={"name":"fox"}

ツッコミ・コメント上等!

  • もっといい手があるよ!とか、ココちがくない?ということがあればコメントよろしくお願いします。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1