[英]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.