Comment choisir au hasard dans un tableau?

559

Je veux savoir s'il existe une façon beaucoup plus propre de procéder. Fondamentalement, je veux choisir un élément aléatoire dans un tableau de longueur variable. Normalement, je le ferais comme ceci:

myArray = ["stuff", "widget", "ruby", "goodies", "java", "emerald", "etc" ]
item = myArray[rand(myarray.length)]

Y a-t-il quelque chose de plus lisible / plus simple pour remplacer la deuxième ligne? Ou est-ce la meilleure façon de le faire. Je suppose que vous pourriez le faire myArray.shuffle.first, mais je ne l'ai vu qu'il y #shufflea quelques minutes sur SO, je ne l'ai pas encore utilisé.

Paul Hoffer
la source
13
Bonne réponse ci-dessous mais un point général sur le shuffle. J'imagine que l'étouffement du tableau complet serait beaucoup plus intensif que l'obtention d'un nombre aléatoire, ce ne serait donc pas une bonne direction à suivre.
Derek Organ

Réponses:

1127

Utilisez simplement Array#sample:

[:foo, :bar].sample # => :foo, or :bar :-)

Il est disponible dans Ruby 1.9.1+. Pour pouvoir également l'utiliser avec une version antérieure de Ruby, vous pouvez require "backports/1.9.1/array/sample".

Notez que dans Ruby 1.8.7, il existe sous le nom malheureux choice; il a été renommé dans une version ultérieure, vous ne devez donc pas l'utiliser.

Bien qu'il ne soit pas utile dans ce cas, sampleaccepte un argument numérique au cas où vous souhaiteriez un certain nombre d'échantillons distincts.

Marc-André Lafortune
la source
1
J'aurais dû savoir que vous auriez une réponse parfaite pour moi (puisque la plupart des questions Ruby que je parcours ici ont votre avis quelque part). Je suis content que vous ayez souligné le versioning; J'utilise 1.9.2. apidock (commentaire de mladen) n'a pas d'échantillon; ruby-doc non plus. À votre avis, quelle est la meilleure référence pour Ruby, mise à jour à 1.9?
Paul Hoffer
En passant, est-il approprié de changer la "bonne réponse" après avoir sélectionné une autre réponse pour la première fois?
Paul Hoffer
1
Merci :-) Et oui, c'est encouragé (voir meta.stackexchange.com/questions/19448/… )
Marc-André Lafortune
J'ai remarqué que votre modification supprimait la mention du 1.8.8. Est-il toujours disponible en version 1.8, et vous modifiez simplement la question car 1.8.8 ne se produira pas?
Andrew Grimm
3
@Andrew: Oui, j'ai modifié ma réponse car 1.8.8 ne se produira pas. Elle devrait toujours être en 1,8 tête, mais cette branche est morte :-(
Marc-André Lafortune
84

myArray.sample(x) peut également vous aider à obtenir x éléments aléatoires du tableau.

beesasoh
la source
6
Il convient de noter que my_array.sample (1)! = My_array.sample
Redithion
5
@Redithion Il convient également de noter que la différence entre: my_array.sample (1) == [sample] et my_array.sample == sample pour fournir explicitement ce que vous voulez dire
Ekkstein
14
myArray.sample

renverra 1 valeur aléatoire.

myArray.shuffle.first

renverra également 1 valeur aléatoire.

JJ21
la source
26
Le shuffle est superflu.
superluminaire
1
Techniquement, cette méthode aléatoire est également correcte stackoverflow.com/a/84747/2047418
Filip Bartuzi
12

Nombre aléatoire d'éléments aléatoires d'un tableau

def random_items(array)
  array.sample(1 + rand(array.count))
end

Exemples de résultats possibles:

my_array = ["one", "two", "three"]
my_array.sample(1 + rand(my_array.count))

=> ["two", "three"]
=> ["one", "three", "two"]
=> ["two"]
Mike Rapadas
la source
@fwilson collections aléatoires d'objets dans n'importe quel ordre. Aussi bon pour tester différentes combinaisons ou générer des données de talon
Mike Rapadas
pourquoi ne pas étendre la classe Array? [] .total_random serait bien plus cool. venir sur son rubis. son objectif!
Tim Kretschmer
Cela ne retournerait jamais un tableau vide. Vous devez placer 1 +dans un endroit différent.
sawa
0
arr = [1,9,5,2,4,9,5,8,7,9,0,8,2,7,5,8,0,2,9]
arr[rand(arr.count)]

Cela retournera un élément aléatoire du tableau.

Si vous utilisez la ligne mentionnée ci-dessous

arr[1+rand(arr.count)]

dans certains cas, il renverra 0 ou une valeur nulle.

La ligne mentionnée ci-dessous

rand(number)

renvoie toujours la valeur de 0 au numéro-1.

Si nous utilisons

1+rand(number)

alors il peut retourner nombre et arr [nombre] ne contient aucun élément.

Muhammad Aamir
la source
-2
class String

  def black
    return "\e[30m#{self}\e[0m"
  end

  def red
    return "\e[31m#{self}\e[0m"
  end

  def light_green
    return "\e[32m#{self}\e[0m"
  end

  def purple
    return "\e[35m#{self}\e[0m"
  end

  def blue_dark
    return "\e[34m#{self}\e[0m"
  end

  def blue_light
    return "\e[36m#{self}\e[0m"
  end

  def white
    return "\e[37m#{self}\e[0m"
  end


  def randColor
    array_color = [
      "\e[30m#{self}\e[0m",
      "\e[31m#{self}\e[0m",
      "\e[32m#{self}\e[0m",
      "\e[35m#{self}\e[0m",
      "\e[34m#{self}\e[0m",
      "\e[36m#{self}\e[0m",
      "\e[37m#{self}\e[0m" ]

      return array_color[rand(0..array_color.size)]
  end


end
puts "black".black
puts "red".red
puts "light_green".light_green
puts "purple".purple
puts "dark blue".blue_dark
puts "light blue".blue_light
puts "white".white
puts "random color".randColor
Charon IV
la source