# How do I acquire a random number of elements from an array?

## Problem

I’m working on a solution to the problem of ‘how to access elements randomly from an array in javascript.’ I discovered a plethora of resources on the subject. Get a random item from a JavaScript array, for example.

``````var item = items[Math.floor(Math.random()*items.length)];
``````

However, we can only select one item from the array in this case. How can we get more than one element if we desire them all? How can we extract many elements from an array?

## Solution #1

There are only two lines:

``````// Shuffle array
const shuffled = array.sort(() => 0.5 - Math.random());

// Get sub-array of first n elements after shuffled
let selected = shuffled.slice(0, n);
``````

## Solution #2

Take a look at this non-destructive (and quick) function:

``````function getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return result;
}
``````

## Solution #3

There is a one-liner solution to this problem.

`````` array.sort(() => Math.random() - Math.random()).slice(0, n)
``````

## Solution #4

_.sample and _.sampleSize are lodash functions.

Gets one or n random elements from a collection with unique keys up to the collection’s size.

``````_.sample([1, 2, 3, 4]);
// => 2

_.sampleSize([1, 2, 3], 2);
// => [3, 1]

_.sampleSize([1, 2, 3], 3);
// => [2, 3, 1]
``````

## Solution #5

Using the Python standard library’s.sample:

``````function sample(population, k){
/*
Chooses k unique random elements from a population sequence or set.

Returns a new list containing elements from the population while
leaving the original population unchanged.  The resulting list is
in selection order so that all sub-slices will also be valid random
samples.  This allows raffle winners (the sample) to be partitioned
into grand prize and second place winners (the subslices).

Members of the population need not be hashable or unique.  If the
population contains repeats, then each occurrence is a possible
selection in the sample.

To choose a sample in a range of integers, use range as an argument.
This is especially fast and space efficient for sampling from a
large population:   sample(range(10000000), 60)

Sampling without replacement entails tracking either potential
selections (the pool) in a list or previous selections in a set.

When the number of selections is small compared to the
population, then tracking selections is efficient, requiring
only a small set and an occasional reselection.  For
a larger number of selections, the pool tracking method is
preferred since the list takes less space than the
set and it doesn't suffer from frequent reselections.
*/

if(!Array.isArray(population))
throw new TypeError("Population must be an array.");
var n = population.length;
if(k < 0 || k > n)
throw new RangeError("Sample larger than population or is negative");

var result = new Array(k);
var setsize = 21;   // size of a small set minus size of an empty list

if(k > 5)
setsize += Math.pow(4, Math.ceil(Math.log(k * 3) / Math.log(4)))

if(n <= setsize){
// An n-length list is smaller than a k-length set
var pool = population.slice();
for(var i = 0; i < k; i++){          // invariant:  non-selected at [0,n-i)
var j = Math.random() * (n - i) | 0;
result[i] = pool[j];
pool[j] = pool[n - i - 1];       // move non-selected item into vacancy
}
}else{
var selected = new Set();
for(var i = 0; i < k; i++){
var j = Math.random() * n | 0;
while(selected.has(j)){
j = Math.random() * n | 0;
}
result[i] = population[j];
}
}

return result;
}
``````

Lib/random.py implementation transferred.

Notes:

In comparison to the acceptable answer: