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
Picking 2 random elements from array
提问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 n
elements
额外的问题,我如何将其扩展到n
元素
回答by georg
回答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.floor
instead of Math.ceil
. The length
property 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 n
random elements you could create a shuffled version of your list and then return the first n
elements of the shuffled array as a result.
如果您想获得n
随机元素,您可以创建列表的混洗版本,然后n
作为结果返回混洗数组的第一个元素。
回答by Mehdi Dehghani
回答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]