Select 2 random elements from an array

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

I still:

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 freezes my page loading.

The best solution?

Additional question, how can I extend this to n elements

+8
javascript jquery
source share
7 answers

DO NOT use loops and comparisons. Instead

  • shuffle an array
  • take the first two elements
+24
source share

Your code will hang if the list contains only one element. Instead of using == I recommend using === , which looks more appropriate in this case.

Also use Math.floor instead of Math.ceil . The length property is <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); } 
+4
source share

http://underscorejs.org/#sample

_. sample (list, [n])

Randomly select from the list. Pass a number to return n random items from the list. Otherwise, one random element is returned.

 _.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 shuffling , as @ thg435 suggested.

+4
source share

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

 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 item cannot be reinstalled and subtract 1 because one item is already selected.

For example, an array of three elements (0, 1, 2). We arbitrarily select element 1. Now the “good” offset value is 0 and 1, offset 0 gives element 2 and offset 1 giving element 0.

Please note that this will give you two random elements with different INDEX and not with a different VALUE value!

+2
source share

If you want to get n random elements, you can create a shuffled version of your list, and then return the first n elements of the shuffled array to it.

+2
source share

If you shuffle the array and concatenate the number of elements you want to return, the return value will contain as many elements as it can if you request more elements than in the array. You can shuffle the actual array or copy using 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 elements from the original array, so that the second call will not include the elements returned by the first call, pass the second argument: 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] 
0
source share

This can be done using the built-in functions ( slice and sort ),

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

All Articles