【小ネタ】JSで要素の組み合わせを列挙する


下記のような、キーの数や要素数が可変のデータの組み合わせを、列挙するjavascriptコードです。
pythonにはitertoolなどの順列・組み合わせ計算を行う定番ライブラリがあるようです。

やっている事ですが、イメージとしては組み合わせを数列に置き換えています。
1桁目が2進数、3桁目が3進数、3桁目が4進数の不規則な進法で表現されていると捉えて、
n[1..234=24]までループでひたすら列挙します。

[code lang=”js”]
var data = {
"1.ドリンク": ["チャイ", "ラッシー"],
"2.副菜": ["サモサ", "ティッカマサラ", "サブジ"],
"3.主菜": ["バターチキン", "キーマ", "ダール", "マトン"]
}

// 実行毎に結果の出力順序が一意になるようにソート
var keys = Object.keys(data).sort();

// 組み合わせの総数を事前に計算
var total = 1;
for (var key in data) {
total *= data[key].length;
}

var q, // 商, ループ中の配列で表現できない数
r, // 余り, ループ中の配列で表現する数
result = []; // 組み合わせを格納する配列

// 組み合わせの総数回ループして、n番目にどの組み合わせが来るかどうかを求める
for (var n=0; n < total; n++) {
result[n] = {};
q = n;

// dataのキー毎にループして、どの要素を使うか決定
for (i=0; i<keys.length; i++) {
key = keys[i];

// ループ対象の配列の要素数で割った余り = その配列で表現できる数
r = q % data[key].length;

// ループ対象の配列の要素数で割った商 = その配列で表現できない数
q = Math.floor(q / data[key].length);

result[n][key] = data[key][r];
}
}

// 出力
for (var i=0; i < result.length; i++) {
console.log(JSON.stringify(result[i]));
}

/*
0:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"バターチキン"}
1:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"バターチキン"}
2:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"バターチキン"}
3:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"バターチキン"}
4:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"バターチキン"}
5:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"バターチキン"}
6:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"キーマ"}
7:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"キーマ"}
8:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"キーマ"}
9:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"キーマ"}
10:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"キーマ"}
11:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"キーマ"}
12:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"ダール"}
13:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"ダール"}
14:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"ダール"}
15:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"ダール"}
16:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"ダール"}
17:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"ダール"}
18:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"マトン"}
19:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"マトン"}
20:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"マトン"}
21:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"マトン"}
22:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"マトン"}
23:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"マトン"}
*/
[/code]

例のデータで言えば2 * 3 * 4通りの組み合わせを求めているので、
例えば15番目の組み合わせをを求める場合、「ドリンク」で表現できる要素の数=2で割ると
商が7、余りが1、…となり、
商の7 = 「副菜」以降で表現しなければならない数
余りの1 = 「ドリンク」で表現する数

よって「ドリンク」は配列の添字[1]の要素「ラッシー」を使うと決定できます。

同様にして、商の7を「副菜」で表現できる3で割ると
商が2、余りが1、…となり、
「副菜」は配列の添字[1]の要素「ティッカマサラ」を使います。

最後の主菜では、2 / 4
商は勿論0、余りは[2]となり、
「主菜の」は配列の添字2の要素の「ダール」に決定します。


DACエンジニア採用情報

  関連記事

【未経験からのRuby on Rails – 第3回】変数と定数

こんにちは。新卒1年目のmatsuariです。 今回はRubyに限らずプログラミングを学ぶ上で非常に重要となる「変数と定数」について、ご紹介していきます。 変数とは・・・ オブジェクトを一時的に格納しておく箱で、オブジェクトを識別するために利用します。 言葉だけでは理解が難しいかと思いますので、まず …

D3.jsとその活用事例について

D3.jsとは? D3とは「Data Driven Document」の略で、データに基づいてドキュメントを操作するための JavaScript ライブラリです。 ご存知の方も多いと思いますが、ちょっとだけD3.jsの基本的な使い方、そして弊社プラットフォームでの利用についてご紹介したいと思います。 …

no image
【小ネタ】Javascriptのconsoleオブジェクトをもっと便利に使う方法

すごく便利なconsoleオブジェクトですが、ブラウザによってサポートされているメソッドが なかったり、そもそもconsoleオブジェクトが使えなかったりと、たまに不便だったりします。 そんなときによく使う便利なコード。 [code language=”javascript” …

【未経験からのRuby on Rails – 第4回】Railsアプリケーション開発をしよう! 〜開発の準備編〜

こんにちは。新卒のmatsuariです。 Rubyについてまだまだ知るべきことはたくさんありますが、とにかく早くアプリを作りたい! ということで、今回はアプリ開発の準備に取り掛かっていきます。 Rubyはアプリを作成しながら、同時に学んでいきたいと思います。 Railsアプリケーション開発の準備《 …

no image
Angular.jsのvalueとfactoryの違いを考える

次のようなHTMLがあったとする。 [code language=”html”] <!doctype html> <html lang="jp" ng-app="App"> <head> <me …

ナイーブベイズで羽生さんと羽生くんを分類してみた

はじめに こんにちは。システム開発部の中村です。 機械学習についての理解を促進するため、 データから分類モデルを自動で構築する古典的な方法である、 ナイーブベイズ分類器を実装してみました。 最近はCloudVisionAPIなど専ら画像解析が流行っていますが、 自分のような初学者には敷居が高そうだっ …

ECMAScript6を使ってみた ~「Promise」編

ECMAScript6とは 一応ちょっとだけ説明しておくと、 ECMAScript(エクマスクリプト)は、Ecma Internationalによって標準化されたスクリプト言語で、バージョン6が2015 年 6 月 17 日に標準仕様として発行されました。(以下、ES6と呼びます) ES6ではcon …

読み方がわからない技術用語 2015

英語圏での読み方を基本的には参考にしています。英語圏でも複数の読み方をしているケースもあるようなので、あくまでも参考程度。2015と書きながら、古い言葉も混じってますが。 async – えーしんく Alt – おると ASUS – えいすーす bower &#8 …

初心者がRailsで開発 – deviseでユーザー認証設定 –

こんにちは、2年目のYukaです。 開発部所属でありながら実は、、 実際に自分で手を動かして開発する機会がなかなかありませんでした。。 しかしついに、、、 開発初心者がRailsでWebアプリの開発に挑戦します!! 今回のゴールは社内でも使用しているGoogleアカウントで簡単にログインができるよう …

SDKってどうやって作ってるの?【Android編】

こんにちは。4度目の投稿です。 現在私はAndroidのSDKを開発しています。 javaにもAndroidにもSDKにも手を出したのは初めてなので、最初はそもそもSDKのイメージが湧かず、ふわふわした状態で始めました。 SDKと調べても「あるソフトウェアを開発するために必要なプログラムや文書などを …