javascript 从数组中选取 2 个随机元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9719434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 07:35:53  来源:igfitidea点击:

Picking 2 random elements from array

javascriptjquery

提问by zsquare

What is the most efficient way to select 2 unique random elements from an array (ie, make sure the same element is not selected twice).

从数组中选择 2 个唯一随机元素的最有效方法是什么(即,确保不会选择两次相同的元素)。

I have so far:

我到目前为止:

var elem1;
var elem2;

elem1 = elemList[Math.ceil(Math.random() * elemList.length)];
do {
  elem2 = elemList[Math.ceil(Math.random() * elemList.length)];
} while(elem1 == elem2)

But this often hangs my page load.

但这通常会挂起我的页面加载。

Any better solution?

有什么更好的解决办法吗?

Extra question, how do I extend this to nelements

额外的问题,我如何将其扩展到n元素

回答by georg

do NOT use loops and comparisons. Instead

不要使用循环和比较。反而

  • shufflethe array
  • take first two elements
  • 打乱数组
  • 取前两个元素

回答by Mars Robertson

http://underscorejs.org/#sample

http://underscorejs.org/#sample

_.sample(list, [n])

Produce a random sample from the list. Pass a number to return n random elements from the list. Otherwise a single random item will be returned.

_.sample(list, [n])

从列表中生成一个随机样本。传递一个数字以从列表中返回 n 个随机元素。否则将返回单个随机项目。

_.sample([1, 2, 3, 4, 5, 6]);
=> 4

_.sample([1, 2, 3, 4, 5, 6], 3);
=> [1, 6, 2]

Looking at the source it uses shufflejust like @thg435 suggested.

查看它使用shuffle的来源,就像@thg435 建议的那样。

回答by Rob W

Your code will hang when the list contains only one item. Instead of using ==, I recommend to use ===, which looks more suitable in this case.

当列表仅包含一项时,您的代码将挂起。==我建议使用===,而不是使用,这在这种情况下看起来更合适。

Also, use Math.floorinstead of Math.ceil. The lengthproperty is equal to <highest index> + 1.

另外,使用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);
}

回答by xanatos

On what Rob W told you, I'll add that a different solution would be to find a random point and for the second point find a random offset from the point:

根据 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];
}

We add 1 because the current element can't be reselected and subtract 1 because one element has already been selected.

我们加 1 是因为当前元素不能被重新选择,减 1 是因为已经选择了一个元素。

For example, an array of three elements (0, 1, 2). We randomly select the element 1. Now the "good" offset value are 0 and 1, with offset 0 giving the element 2 and offset 1 giving the element 0.

例如,一个包含三个元素 (0, 1, 2) 的数组。我们随机选择元素 1。现在“好”偏移值是 0 和 1,偏移 0 给出元素 2,偏移 1 给出元素 0。

Note that this will give you two random elements with different INDEX, not with different VALUE!

请注意,这将为您提供两个具有不同 INDEX 的随机元素,而不是具有不同 VALUE 的元素!

回答by sietschie

If you want to get nrandom elements you could create a shuffled version of your list and then return the first nelements of the shuffled array as a result.

如果您想获得n随机元素,您可以创建列表的混洗版本,然后n作为结果返回混洗数组的第一个元素。

回答by Mehdi Dehghani

It can be done using built-in functionality (sliceand sort),

可以使用内置功能(slicesort)来完成,

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

回答by Jerry

While shuffle the array and pick the first two is correct.
You don't need to shuffle the whole array.

虽然洗牌数组并选择前两个是正确的。
您不需要打乱整个数组。

Just shuffle the first two!

只需洗牌前两个!

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))

basically the same as https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle基本相同

Except you just quit early when you have enough item shuffled.

除非您在洗牌的项目足够多时提前退出。

回答by michelepatrassi

You can do something easy like this

你可以做一些像这样简单的事情

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 and b will be your random elements.

a 和 b 将是您的随机元素。

回答by kennebec

If you shuffle the array and splice the number of elements you want to return, the return value will contain as many items as it can, if you ask for more items than are in the array. You can shuffle the actual array or a copy, with slice().

如果您打乱数组并拼接要返回的元素数量,则返回值将包含尽可能多的项目,如果您要求的项目多于数组中的项目。您可以使用 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]

If you want to remove the selected items from the original array, so that a second call will not include the elements the first call returned, pass a second argument: getRandom(3,true);

如果要从原始数组中删除所选项目,以便第二次调用不会包含第一次调用返回的元素,请传递第二个参数: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]