如何在没有条件替换的情况下随机化?
How to randomize without replacement with conditions?
我有一些嵌入的图像,我将它们随机化了 4 次而没有替换(一旦图像被看到,你就不能再看到它)。我想添加一个条件,这表明无法看到一组附加图像(不仅是之前选择的图像)。这些图像与所选图像具有相似特征。
演示:
假设我有以下变量数组:
BF1, BA1, BF2, BA2, BF3, BA3
我想从数组中随机抽取 3 个变量(图像)而不进行替换,并且我还希望从下一个数组中删除编号为 2(同一组)的变量。所以,如果第一次绘制的 var 是 BF2,那么下一次绘制将来自以下数组:
BF1, BA1, BF3, BA3
(只能随机出现一个选项)
现在假设我绘制了变量 BF1
,那么下一组可能的变量将是:
BF3, BA3
.
我希望这是有道理的。这是我到目前为止没有替换的绘图代码:
function shuffle(array){
var counter = array.length,
temp, index;
while (counter > 0){
index = Math.floor(Math.random() * counter);
counter = counter-1;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
var myArray = [BF1,BA1,BF2, BA2, BF3,BA3, BA4, BF4, BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BA17, BF17, BA18, BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, BF26, BA27, BF27, BA28, BF28, BA29, BF29, BA30, BF30, BA31, BF31, BA32, BF33, BA33, BA34, BF35, BA35, BA36, BF36];
shuffle(myArray)
您可以使用循环和随机数打乱数组,然后在另一个循环中提取结果数组中的第一张图像,过滤字符串末尾带有数字的数组
var myArray="BF1, BA1, BF2, BA2, BF3, BA3, BA4, BF4, BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BA17, BF17, BA18, BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, BF26, BA27, BF27, BA28, BF28, BA29, BF29, BA30, BF30, BA31, BF31, BA32, BF33, BA33, BA34, BF35, BA35, BA36, BF36";
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
const arr = shuffle(myArray.split(','));
function draw(a, times) {
let res =[]
for (let i = 1; i <= times; i++) {
let str = a[0]
res.push(str)
a = a.filter(a => parseInt(a.match(/\d+$/)[0], 10) !== parseInt(str.match(/\d+$/)[0], 10))
}
return res
}
console.log(draw(arr, 4))
您当然可以通过多种方式实现这一点,但无论您使用什么,您都需要以某种身份执行以下 3 个步骤(我将它们拆分为单独的方法,但您可以将它们组合起来如您所愿):
- 随机播放列表
- 选择一个项目
- 筛选出符合选择的项目(在本例中,具有相同编号的项目)
您已经涵盖了洗牌例程,所以只剩下挑选和过滤器了。
对于选择,我只是使用 Math.random
从列表中随机拉取一个成员:
return array[Math.floor(Math.random() * array.length)];
对于过滤器,我使用 Array.prototype.filter
来提取所需的项目。在这种情况下,对于字符串,我从字符串中解析出数字,然后删除数组中与最后一次选择具有相同数字的所有项目:
return array.filter(el => +el.match(/\d+/).join() != +picked.match(/\d+/).join());
但是对于实际图像,您只需将其替换为您阅读图像标签的方式即可。
例子
这是完整的工作示例,首先是精选列表,然后是经过排序的精选数组,显示它们都已被使用。
var imageList = ['BF1', 'BA1', 'BF2', 'BA2', 'BF3', 'BA3', 'BA4', 'BF4', 'BA5', 'BF5', 'BF6', 'BA6', 'BF7', 'BA7', 'BA8', 'BF8', 'BA9', 'BF9', 'BF10', 'BA10', 'BA11', 'BF11', 'BA12', 'BF12', 'BA13', 'BF13', 'BA14', 'BF14', 'BA15', 'BF15', 'BA16', 'BF16', 'BA17', 'BF17', 'BA18', 'BF18', 'BA19', 'BF19', 'BA20', 'BF20', 'BA21', 'BF21', 'BF22', 'BA23', 'BF23', 'BA24', 'BF24', 'BA25', 'BF25', 'BA26', 'BF26', 'BA27', 'BF27', 'BA28', 'BF28', 'BA29', 'BF29', 'BA30', 'BF30', 'BA31', 'BF31', 'BA32', 'BF33', 'BA33', 'BA34', 'BF35', 'BA35', 'BA36', 'BF36'];
var selection = imageList.slice();
var picked = [];
function shuffle(array) {
var counter = array.length, temp, index;
while (counter > 0) {
index = Math.floor(Math.random() * counter);
counter = counter - 1;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
function pick(array) {
return array[Math.floor(Math.random() * array.length)];
}
function filterPicked(picked, array) {
return array.filter(el => +el.match(/\d+/).join() != +picked.match(/\d+/).join());
}
while (selection.length) {
// 1. Shuffle
shuffle(selection);
// 2. Pick
picked.push(pick(selection));
// 3. Filter
selection = filterPicked(picked[picked.length-1], selection);
}
console.log(`Picks: [${picked.join(', ')}]`);
console.log(`Sorted picks: [${picked.sort((a, b) => +a.match(/\d+/).join() - +b.match(/\d+/).join()).join(', ')}]`);
循序渐进
- 打乱选择数组(完整数组或所有选择的副本)
- 从选择数组中选择一个项目,将其推入选择数组
- 过滤选择数组以删除与上次选择匹配的项目
- 对每个新过滤的数组重复 1-3,直到没有选择剩余
我有一些嵌入的图像,我将它们随机化了 4 次而没有替换(一旦图像被看到,你就不能再看到它)。我想添加一个条件,这表明无法看到一组附加图像(不仅是之前选择的图像)。这些图像与所选图像具有相似特征。
演示:
假设我有以下变量数组:
BF1, BA1, BF2, BA2, BF3, BA3
我想从数组中随机抽取 3 个变量(图像)而不进行替换,并且我还希望从下一个数组中删除编号为 2(同一组)的变量。所以,如果第一次绘制的 var 是 BF2,那么下一次绘制将来自以下数组:
BF1, BA1, BF3, BA3
(只能随机出现一个选项)
现在假设我绘制了变量 BF1
,那么下一组可能的变量将是:
BF3, BA3
.
我希望这是有道理的。这是我到目前为止没有替换的绘图代码:
function shuffle(array){
var counter = array.length,
temp, index;
while (counter > 0){
index = Math.floor(Math.random() * counter);
counter = counter-1;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
var myArray = [BF1,BA1,BF2, BA2, BF3,BA3, BA4, BF4, BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BA17, BF17, BA18, BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, BF26, BA27, BF27, BA28, BF28, BA29, BF29, BA30, BF30, BA31, BF31, BA32, BF33, BA33, BA34, BF35, BA35, BA36, BF36];
shuffle(myArray)
您可以使用循环和随机数打乱数组,然后在另一个循环中提取结果数组中的第一张图像,过滤字符串末尾带有数字的数组
var myArray="BF1, BA1, BF2, BA2, BF3, BA3, BA4, BF4, BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BA17, BF17, BA18, BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, BF26, BA27, BF27, BA28, BF28, BA29, BF29, BA30, BF30, BA31, BF31, BA32, BF33, BA33, BA34, BF35, BA35, BA36, BF36";
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
const arr = shuffle(myArray.split(','));
function draw(a, times) {
let res =[]
for (let i = 1; i <= times; i++) {
let str = a[0]
res.push(str)
a = a.filter(a => parseInt(a.match(/\d+$/)[0], 10) !== parseInt(str.match(/\d+$/)[0], 10))
}
return res
}
console.log(draw(arr, 4))
您当然可以通过多种方式实现这一点,但无论您使用什么,您都需要以某种身份执行以下 3 个步骤(我将它们拆分为单独的方法,但您可以将它们组合起来如您所愿):
- 随机播放列表
- 选择一个项目
- 筛选出符合选择的项目(在本例中,具有相同编号的项目)
您已经涵盖了洗牌例程,所以只剩下挑选和过滤器了。
对于选择,我只是使用 Math.random
从列表中随机拉取一个成员:
return array[Math.floor(Math.random() * array.length)];
对于过滤器,我使用 Array.prototype.filter
来提取所需的项目。在这种情况下,对于字符串,我从字符串中解析出数字,然后删除数组中与最后一次选择具有相同数字的所有项目:
return array.filter(el => +el.match(/\d+/).join() != +picked.match(/\d+/).join());
但是对于实际图像,您只需将其替换为您阅读图像标签的方式即可。
例子
这是完整的工作示例,首先是精选列表,然后是经过排序的精选数组,显示它们都已被使用。
var imageList = ['BF1', 'BA1', 'BF2', 'BA2', 'BF3', 'BA3', 'BA4', 'BF4', 'BA5', 'BF5', 'BF6', 'BA6', 'BF7', 'BA7', 'BA8', 'BF8', 'BA9', 'BF9', 'BF10', 'BA10', 'BA11', 'BF11', 'BA12', 'BF12', 'BA13', 'BF13', 'BA14', 'BF14', 'BA15', 'BF15', 'BA16', 'BF16', 'BA17', 'BF17', 'BA18', 'BF18', 'BA19', 'BF19', 'BA20', 'BF20', 'BA21', 'BF21', 'BF22', 'BA23', 'BF23', 'BA24', 'BF24', 'BA25', 'BF25', 'BA26', 'BF26', 'BA27', 'BF27', 'BA28', 'BF28', 'BA29', 'BF29', 'BA30', 'BF30', 'BA31', 'BF31', 'BA32', 'BF33', 'BA33', 'BA34', 'BF35', 'BA35', 'BA36', 'BF36'];
var selection = imageList.slice();
var picked = [];
function shuffle(array) {
var counter = array.length, temp, index;
while (counter > 0) {
index = Math.floor(Math.random() * counter);
counter = counter - 1;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
function pick(array) {
return array[Math.floor(Math.random() * array.length)];
}
function filterPicked(picked, array) {
return array.filter(el => +el.match(/\d+/).join() != +picked.match(/\d+/).join());
}
while (selection.length) {
// 1. Shuffle
shuffle(selection);
// 2. Pick
picked.push(pick(selection));
// 3. Filter
selection = filterPicked(picked[picked.length-1], selection);
}
console.log(`Picks: [${picked.join(', ')}]`);
console.log(`Sorted picks: [${picked.sort((a, b) => +a.match(/\d+/).join() - +b.match(/\d+/).join()).join(', ')}]`);
循序渐进
- 打乱选择数组(完整数组或所有选择的副本)
- 从选择数组中选择一个项目,将其推入选择数组
- 过滤选择数组以删除与上次选择匹配的项目
- 对每个新过滤的数组重复 1-3,直到没有选择剩余