組み合わせ生成のgemを作った
先日のミートアップで発表した内容をあらためてまとめます。
コンセプト
pictやPairwiserを使って組み合わせテストのパターンを作るのは楽になったが、rspecで使うためには加工が必要なので、組み合わせたいパラメーターを渡したら配列にして返ってきて欲しい。
No. | first_name | last_name |
---|---|---|
1 | “aaa” | “bbb” |
2 | “あああ” | “” |
: | : | : |
みたいなやつを
where(:no, :first_name, :last_name) do [ [1, "aaa", "bbb"], [2, "test", "bbb"], [3, "あああ", ""], ] end
のようにイイ感じに整形しないといけない。
※繰り返しのテストには、以下のgemを利用しています。 github.com
そこで、senju_kan_nonというgemを作って公開しました!!! (yamlのパーサーを書けばよかったのではないか。)
Why senju_kan_non?
gemの名前を考えていた時に、パラメーターを衆生に見立てて、テストケースによって救われるみたいなことを考えてこんな名前になりました。
その結果、メソッド名やパラメーター名に合掌 🙏 とか、利益とか、一切衆生とか使ってます。 正直読みづらい。
アルゴリズムの紹介
高校数学をちょっと思い出す。
異なる n 個のものから r 個を選ぶ場合の、組み合わせの数
Rubyの便利メソッドをつかう
combination
[1,2,3,4].combination(2) do |first, second| p "(#{first, #{second}})" end => (1,2) (1,3) (1,4) (2,3) (2,4) (3,4)
これで、2引数のarrayを組み合わせるのが実現できる。
{ :first=>[1, 1, 1, 2, 2, 2, 3, 3, 3], :second=>["a", "b", "c", "a", "b", "c", "a", "b", "c"] }
テーブルにすると、こんな感じ。
key | v1 | v2 | v3 | ・・・ |
---|---|---|---|---|
first | 1 | 1 | 1 | ・・・ |
second | a | b | c | ・・・ |
目指すのはこの形なので、
No. | first_name | last_name |
---|---|---|
1 | “aaa” | “bbb” |
2 | “あああ” | “” |
: | : | : |
行列を入れ替えたい。
Rubyの便利メソッドをつかう2
transpose
values = { :first=>[1, 1, 1, 2, 2, 2, 3, 3, 3], :second=>["a", "b", "c", "a", "b", "c", "a", "b", "c"]} values.transpose => [[1, "a"], [1, "b"], [1, "c"], [2, "a"], [2, "b"], [2, "c"], [3, "a"], [3, "b"], [3, "c"]]
以上をベースに、重複したパターンの削除、テーブル作成時に欠損するデータの補完処理を足した。
これから作ろうと思っているところ
- 網羅する水準の指定ができるようにしたい。
- 組み合わせを作るアルゴリズムを高速に。
- 禁則処理
- 出力された組み合わせをファイル出力
発表した時は忘れてましたが、すでに便利なgemがあるので、そっちを使ってもいいと思います。