簡體   English   中英

從數組中選取 2 個隨機元素

[英]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);
}

可以使用內置功能( slicesort )來完成,

var n = 2
    randomItems = array.sort(() => .5 - Math.random()).slice(0, n);

在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM