91 votes

Prendre n éléments aléatoires dans une Liste<E> ?

Comment prendre n éléments au hasard dans un ArrayList<E> ? Idéalement, j'aimerais pouvoir faire des appels successifs à la fonction take() pour obtenir x autres éléments, sans remplacement.

0voto

Toutes ces réponses nécessitent une liste modifiable ou se heurtent à des problèmes de performance.

Voici un extrait rapide qui nécessite O(k) d'espace supplémentaire, qui est garanti en O(k) de temps et qui n'a pas besoin d'un tableau modifiable. (Effectue des mélanges dans une carte)

  func getRandomElementsFrom(array: [Int], count: Int = 8) -> [Int] {
    if array.count <= count {
        return array
    }

    var mapper = [Int: Int]()
    var results = [Int]()

    for i in 0..<count {
        let randomIndex = Int.random(in: 0..<array.count - i)

        if let existing = mapper[randomIndex] {
            results.append(array[existing])
        } else {
            let element = array[randomIndex]
            results.append(element)
        }

        let targetIndex = array.count - 1 - i
        mapper[randomIndex] = mapper[targetIndex] ?? targetIndex 
    }

    return results
}

-1voto

Aldo Canepa Points 499

La méthode suivante renvoie un nouveau Liste d'éléments aléatoires Min(n, list.size()) extraites de la liste des paramètres. N'oubliez pas que la liste est modifiée après chaque appel. Par conséquent, chaque appel "consommera" la liste originale qui sera renvoyée. n des éléments aléatoires :

public static <T> List<T> nextRandomN(List<T> list, int n) {
  return Stream
    .generate(() -> list.remove((int) (list.size() * Math.random())))
    .limit(Math.min(list.size(), n))
    .collect(Collectors.toList());
}

Exemple d'utilisation :

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

System.out.println(nextRandomN(list, 3).toString());
System.out.println(nextRandomN(list, 3).toString());
System.out.println(nextRandomN(list, 3).toString());
System.out.println(nextRandomN(list, 3).toString());

Exemple de sortie :

[8, 2, 3]
[4, 10, 7]
[1, 5, 9]
[6]

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