JSFiddle - React, Tailwind, and code Playground
HTML
<button onclick="run()">run</button>
JavaScript
(function(global){
// algorithm - 重みをつけて乱択する http://blog.livedoor.jp/dankogai/archives/51761113.html
// バイナリサーチ版
var make_random_picker = function(picks){
var i, l = picks.length, t = 0, choices = picks.concat();
for (i = 0; i < l; ++i) { choices[i][1] = (t += choices[i][1]); }
for (i = 0; i < l; ++i) { choices[i][1] /= t; }
return function() {
var r = Math.random(), head = 0, tail = l - 1;
while (head <= tail) {
var sum = head + tail;
var mid = (sum <= 0x7fffffff) ? (sum >> 1) : Math.floor(sum / 2);
if (r < choices[mid][1]) {
if (mid == 0 || r >= choices[mid-1][1]) {
return choices[mid][0];
}
tail = mid - 1;
}
else {
head = mid + 1;
}
}
return null; // never.
};
};
// 実行
global.run = function() {
var data = [];
var result = {'null' : 0};
for (var i = 0; i < 100; i++) {
var key = 'nnn' + i;
data.push([key, 1]);
result[key] = 0;
}
var s = new Date();
var pick = make_random_picker(data);
alert('make time:' + (new Date() - s) + '(ms)');
var s = new Date();
var n = 100000;
for(var i = 0; i < n; i++) {
var v = pick();
result[v]++;
}
if (!confirm('run time:' + (new Date() - s) + '(ms). cancel print log?')) {
var buf = [];
buf.push('null:' + result['null'] + '(' + ((result['null']/n)*100).toFixed(3) + '%)');
for (var i = 0; i < data.length; i++) {
buf.push(data[i][0] + ':' + result[data[i][0]]+'(' + ((result[data[i][0]]/n)*100).toFixed(3) + '%)');
}
log(buf.join('\n'));
function log(s) {
if (window.console) console.log(s);
else if (window.opera) opera.postError(s);
}
}
};
})(this)