[英]How to Influence Math.Random to Make Numbers More Likely?
我試圖弄清楚如何影響Math.random()
以便timesSinceLastSelected
的計數器具有更高數字的項目被選中的機會更高。
例如,如果“item1”的 timesSinceLastSelected 為 4,而“item2”的 timesSinceLastSelected 為 3,則“item1”可能有 75% 被選中,但“item2”仍有 25% 的機會,即使您不選擇不知道數組中有多少項。
let arr = [{ //Unknown number of items
"name": "item1",
"deselected": false,
"favourite": false,
"timesSinceLastSelected": 0
},
{
"name": "item2",
"deselected": false,
"favourite": true,
"timesSinceLastSelected": 0
},
{
"name": "item3",
"deselected": true,
"favourite": false,
"timesSinceLastSelected": 0
},
{
"name": "item4",
"deselected": true,
"favourite": true,
"timesSinceLastSelected": 0
}
];
$('#button').click(function() {
// Selecting only the items where deselected = false
let filter_deselected = arr.filter(val => val.deselected === false);
// Selecting only the items where favourite = true
let filter_favourite = filter_deselected.filter(val => val.favourite === true);
// How do I make timesSinceLastSelected with higher numbers more likely?
if (Math.round(Math.random() * 10 > 5)) { // Selecte random item
var selected = Math.floor(Math.random() * filter_deselected.length);
} else { // Select random favourite item
var selected = Math.floor(Math.random() * filter_favourite.length);
}
// Adding 1 to every item's counter
arr.forEach(function(val) {
val.timesSinceLastSelected++;
});
// Returning the selected item's counter back to 0
filter_deselected[selected].timesSinceLastSelected = 0;
// Logging the randomly selected item
console.log(filter_deselected[selected]);
});
您可以獲得未選擇計數的總和,並獲得一個隨機數,直到總和並獲得該項目。
然后更新未選中的並重置選中的項目。
開始時,給所有項目一個以進行平均分配。
const getRandom = () => { let sum = items.reduce((s, { timesNotSelected }) => s + timesNotSelected, 0), random = Math.random() * sum, item = items.find(({ timesNotSelected }) => (random -= timesNotSelected) <= 0); items.forEach(o => o.timesNotSelected = o === item? 1: o.timesNotSelected + 1) return item; }, items = [{ id: 1, timesNotSelected: 1 }, { id: 2, timesNotSelected: 1 }, { id: 3, timesNotSelected: 1 }, { id: 4, timesNotSelected: 1 }]; console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items); console.log(getRandom().id); console.log(items);
.as-console-wrapper { max-height: 100%;important: top; 0; }
const getSum = (data, key) => data.reduce((sum, { [key]: n }) => sum += (n + 1), 0);
const randomThreshold = (data, key) => ~~(Math.random() * getSum(data, key));
const randomElement = (data, key, threshold = null, total = 0, i = 0) => {
const datum = data[i];
const newTotal = total + datum[key] + 1;
const newThreshold = threshold || randomThreshold(data, key);
return newTotal >= newThreshold ? datum : randomElement(data, key, newThreshold, newTotal, i + 1);
}
像這樣使用:
console.log(randomElement(items, 'timesSinceLastSelected').name)
const items = [ { "name": "item1", "deselected": false, "favourite": false, "timesSinceLastSelected": 4 }, { "name": "item2", "deselected": false, "favourite": true, "timesSinceLastSelected": 3 }, { "name": "item3", "deselected": true, "favourite": false, "timesSinceLastSelected": 2 }, { "name": "item4", "deselected": true, "favourite": true, "timesSinceLastSelected": 1 } ]; const getSum = (data, key) => data.reduce((sum, { [key]: n }) => sum += (n + 1), 0); const randomThreshold = (data, key) => ~~(Math.random() * getSum(data, key)); const randomElement = (data, key, threshold = null, total = 0, i = 0) => { const datum = data[i]; const newTotal = total + datum[key] + 1; const newThreshold = threshold || randomThreshold(data, key); return newTotal >= newThreshold? datum: randomElement(data, key, newThreshold, newTotal, i + 1); } for (let i = 0; i < 10; i++) { console.log(randomElement(items, 'timesSinceLastSelected').name); }
基於這篇文章。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.