[英]Picking 2 random elements from array
从数组中选择 2 个唯一随机元素的最有效方法是什么(即,确保同一元素未被选择两次)。
我到目前为止:
var elem1;
var elem2;
elem1 = elemList[Math.ceil(Math.random() * elemList.length)];
do {
elem2 = elemList[Math.ceil(Math.random() * elemList.length)];
} while(elem1 == elem2)
但这经常挂起我的页面加载。
有更好的解决方案吗?
额外的问题,我如何将其扩展到n
元素
不要使用循环和比较。 反而
http://underscorejs.org/#sample
_.sample(list, [n])
从列表中生成一个随机样本。 传递一个数字以从列表中返回 n 个随机元素。 否则将返回单个随机项目。
_.sample([1, 2, 3, 4, 5, 6]);
=> 4
_.sample([1, 2, 3, 4, 5, 6], 3);
=> [1, 6, 2]
查看它使用shuffle的来源,就像@thg435 建议的那样。
当列表仅包含一项时,您的代码将挂起。 我建议使用===
而不是使用==
,这在这种情况下看起来更合适。
另外,使用Math.floor
而不是Math.ceil
。 length
属性等于<highest index> + 1
。
var elem1;
var elem2;
var elemListLength = elemList.length;
elem1 = elemList[Math.floor(Math.random() * elemListLength)];
if (elemListLength > 1) {
do {
elem2 = elemList[Math.floor(Math.random() * elemListLength)];
} while(elem1 == elem2);
}
在 Rob W 告诉您的内容中,我要补充一点,另一种解决方案是找到一个随机点,并为第二个点找到与该点的随机偏移量:
var elem1;
var elem2;
var elemListLength = elemList.length;
var ix = Math.floor(Math.random() * elemListLength);
elem1 = elemList[ix];
if (elemListLength > 1) {
elem2 = elemList[(ix + 1 + Math.floor(Math.random() * (elemListLength - 1))) % elemListLength];
}
我们加 1 是因为当前元素不能被重新选择,减 1 是因为已经选择了一个元素。
例如,一个包含三个元素 (0, 1, 2) 的数组。 我们随机选择元素 1。现在“好”偏移值是 0 和 1,偏移 0 给出元素 2,偏移 1 给出元素 0。
请注意,这将为您提供两个具有不同 INDEX 的随机元素,而不是具有不同 VALUE 的元素!
如果您想获得n
随机元素,您可以创建列表的混洗版本,然后返回混洗数组的前n
元素。
虽然洗牌数组并选择前两个是正确的。
您不需要打乱整个数组。
只需洗牌前两个!
var arrElm = [1, 2, 3, 4, 5, 6, 7]
var toTake = 2
var maxToShuffle = Math.min(arrElm.length - 1, toTake)
for (let i = 0; i < maxToShuffle; i++) {
const toSwap = i + Math.floor(Math.random() * (arrElm.length - i))
;[arrElm[i], arrElm[toSwap]] = [arrElm[toSwap], arrElm[i]]
}
console.log(arrElm.slice(0, toTake))
与https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle基本相同
除非你有足够的物品洗牌时提前退出。
你可以做一些像这样简单的事情
const elements = ['indie hackers', 'twitter', 'product hunt', 'linkedIn'];
const randomIndex = Math.floor(Math.random() * elements.length);
const a = elements[randomIndex];
const filteredElements = [...elements].splice(randomIndex, 1);
const b = filteredElements[Math.floor(Math.random() * elements.length)];
a 和 b 将是您的随机元素。
我发现这是最有用的技术之一:
var index1 = Math.floor(Math.random() * array.length);
var index2 = Math.floor(Math.random() * (array.length-1));
if index1 == index2 {
index2 += 1;
}
您不能越界,因为 index2 无法获取最后一个元素。
如果您打乱数组并拼接要返回的元素数量,则返回值将包含尽可能多的项目,如果您要求的项目多于数组中的项目。 您可以使用 slice() 对实际数组或副本进行混洗。
Array.prototype.getRandom= function(num, cut){
var A= cut? this:this.slice(0);
A.sort(function(){
return .5-Math.random();
});
return A.splice(0, num);
}
var a1= [1, 2, 3, 4, 5];
a1.getRandom(2)
>>[4, 2]
如果要从原始数组中删除所选项目,以便第二次调用不会包含第一次调用返回的元素,请传递第二个参数:getRandom(3,true);
window.Memry=window.Memry || {};
Memry.a1= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
Memry.a1.getRandom(3,true);
>>[5,10,7]
Memry.a1.getRandom(3,true);
>>[3,9,6]
Memry.a1.getRandom(3,true);
>>[8,4,1]
Memry.a1.getRandom(3,true);
>>[2]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.