从数组中选择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
元素
答案 0 :(得分:29)
不要使用循环和比较。代替
答案 1 :(得分:5)
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建议一样。
答案 2 :(得分:4)
当列表只包含一个项目时,您的代码将挂起。我建议不要使用==
,而是使用===
,在这种情况下看起来更合适。
另外,请使用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);
}
答案 3 :(得分:3)
关于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!
答案 4 :(得分:2)
如果你想获得n
随机元素,你可以创建一个混乱版本的列表,然后返回混洗数组的第一个n
元素。
答案 5 :(得分:2)
var n = 2
randomItems = array.sort(() => .5 - Math.random()).slice(0, n);
答案 6 :(得分:0)
如果您将数组洗牌并拼接您想要返回的元素数量, 返回值将包含尽可能多的项目, 如果你要求的项目多于阵列中的项目。 您可以使用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]
答案 7 :(得分:0)
在随机排列数组并选择前两个数组时是正确的。
您不需要重新整理整个数组。
只需随机播放前两个!
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
除非您洗完足够的物品后才提前退出。
答案 8 :(得分:0)
您可以像这样简单地做
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将是您的随机元素。