190 votes

Comment obtenir un nombre d'éléments aléatoires à partir d'un tableau ?

Je travaille sur "comment accéder à des éléments de manière aléatoire à partir d'un tableau en javascript". J'ai trouvé de nombreux liens à ce sujet. Par exemple : Obtenir un élément aléatoire d'un tableau JavaScript

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

Mais dans ce cas, nous ne pouvons choisir qu'un seul élément du tableau. Si nous voulons plus d'un élément, comment pouvons-nous y parvenir ? Comment obtenir plus d'un élément d'un tableau ?

14voto

Derek 朕會功夫 Points 23487

Portage .sample de la bibliothèque standard de Python :

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;
            }
            selected.add(j);
            result[i] = population[j];
        }
    }

    return result;
}

Mise en œuvre portée de Lib/random.py .

Notes :

  • setsize est défini en fonction des caractéristiques de Python pour des raisons d'efficacité. Bien qu'il n'ait pas été adapté à JavaScript, l'algorithme fonctionnera toujours comme prévu.
  • Certaines autres réponses décrites dans cette page ne sont pas sûres selon la spécification ECMAScript en raison d'une mauvaise utilisation de Array.prototype.sort . Cet algorithme est cependant garanti de se terminer en temps fini.
  • Pour les navigateurs plus anciens qui n'ont pas de Set l'ensemble peut être remplacé par un Array y .has(j) remplacé par .indexOf(j) > -1 .

Performance par rapport à la réponse acceptée :

13voto

Créer une fonction qui fait cela :

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
        result.push(sourceArray[Math.floor(Math.random()*sourceArray.length)]);
    }
    return result;
}

vous devez également vérifier si le tableau source contient suffisamment d'éléments pour être renvoyé. et si vous souhaitez que des éléments uniques soient renvoyés, vous devez supprimer l'élément sélectionné du tableau source.

11voto

Rory McCrossan Points 69838

Si vous souhaitez récupérer des éléments du tableau de manière aléatoire dans une boucle sans répétitions, vous pouvez supprimer l'élément sélectionné du tableau à l'aide de la commande splice :

var items = [1, 2, 3, 4, 5];
var newItems = [];

for (var i = 0; i < 3; i++) {
  var idx = Math.floor(Math.random() * items.length);
  newItems.push(items[idx]);
  items.splice(idx, 1);
}

console.log(newItems);

7voto

Yair Levy Points 166

Syntaxe ES6

const pickRandom = (arr,count) => {
  let _arr = [...arr];
  return[...Array(count)].map( ()=> _arr.splice(Math.floor(Math.random() * _arr.length), 1)[0] ); 
}

5voto

DedaDev Points 1838

Je n'arrive pas à croire que personne n'ait mentionné cette méthode, plutôt propre et directe.

const getRnd = (a, n) => new Array(n).fill(null).map(() => a[Math.floor(Math.random() * a.length)]);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X