web-dev-qa-db-fra.com

Obtenir des éléments aléatoires à partir d'une liste

Je cherche essentiellement un équivalent Elixir de Ruby Array#sample . Quelque chose qui me permettrait de faire ça:

list = [1,2,3,4,5,6,7]

sample(list)
#=> 4

sample(list, 3)
#=> [6, 2, 5]

Je n'ai rien trouvé non plus dans le Elixir List Docs .

29
Sheharyar

Réponse mise à jour

Comme José Valim l'a dit dans sa réponse , dans Elixir 1.1 Et au-dessus, vous pouvez maintenant utiliser ces méthodes pour obtenir des éléments aléatoires à partir d'une liste:

Exemple:

Enum.random(list)                         #=> 4

Enum.take_random(list, 3)                 #=> [3, 9, 1]
Enum.take_random(list, 1)                 #=> [7]

N'oubliez pas d'appeler :random.seed(:erlang.now) d'abord !


Réponse originale

Je ne suis toujours pas en mesure de trouver un moyen "approprié" et "magique" de le faire, mais c'est le mieux que j'ai pu trouver:

Pour obtenir un seul élément aléatoire:

list |> Enum.shuffle |> hd
#=> 4

Remarque: Cela donne une exception si le list est vide

Pour obtenir plusieurs éléments aléatoires:

list |> Enum.shuffle |> Enum.take(3)
#=> [7, 1, 5]
50
Sheharyar

Il n'y a pas une telle fonction dans Elixir 1.0, vous devez donc l'implémenter vous-même comme mentionné par les autres solutions. Cependant, Enum.random/1 vient avec Elixir v1.1: https://hexdocs.pm/elixir/Enum.html#random/1

10
José Valim

Une autre façon (pour échantillonner un seul élément) est:

list |> Enum.at(:random.uniform(length(list)) - 1)

Peut-être préférable à l'autre méthode si vous travaillez avec des listes suffisamment grandes pour que le mélange de la liste entière puisse avoir un impact sur les performances.

commentaire de Gazler sur l'utilisation de :random.seed(:erlang.now) s'applique toujours.

5
Simon Woolf

Si vous utilisez une version plus récente d'Elixir, il y a Enum.take_random/2 fonction ajoutée dans Elixir v1.1.

De la version 1.1 d'Elixir documentation :

Prend des éléments aléatoires d'une collection.

Notez que cette fonction traversera toute la collection pour obtenir la sous-liste aléatoire de la collection. Si vous voulez le nombre aléatoire entre deux entiers, la meilleure option est d'utiliser le module: random.

Donc, répondre à la question, prendre plusieurs éléments de la liste ressemblerait à:

list = [1,2,3,4,5,6,7]
Enum.take_random(list, 3)
#=> [2, 4, 1]

Ou, pour un seul article:

list = [1,2,3,4,5,6,7]
Enum.take_random(list, 1)
#=> [1]
1
Ilija Eftimov