622

I want to know if there is a much cleaner way of doing this. Basically, I want to pick a random element from an array of variable length. Normally, I would do it like this:

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

Is there something that is more readable / simpler to replace the second line? Or is that the best way to do it. I suppose you could do myArray.shuffle.first, but I only saw #shuffle a few minutes ago on SO, I haven't actually used it yet.

the Tin Man
  • 155,156
  • 41
  • 207
  • 295
Paul Hoffer
  • 12,291
  • 6
  • 26
  • 37
  • 13
    Good Answer below but a general point about shuffle. I would imagine suffling the full array would be much more intensive than just getting a random number so it wouldn't be a good direction to go. – Derek Organ Dec 19 '11 at 18:50

6 Answers6

1232

Just use Array#sample:

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

It is available in Ruby 1.9.1+. To be also able to use it with an earlier version of Ruby, you could require "backports/1.9.1/array/sample".

Note that in Ruby 1.8.7 it exists under the unfortunate name choice; it was renamed in later version so you shouldn't use that.

Although not useful in this case, sample accepts a number argument in case you want a number of distinct samples.

Marc-André Lafortune
  • 75,965
  • 16
  • 156
  • 164
  • 1
    I should have known that you would have a perfect answer for me (since most Ruby questions I browse here have your input somewhere). I am glad you pointed out the versioning; I am using 1.9.2. apidock (mladen's comment) does not have sample; neither does ruby-doc. In your opinion, what is the best reference for Ruby, updated to 1.9? – Paul Hoffer Aug 15 '10 at 01:15
  • On a side note, is it proper to change the "correct answer" after I have first selected another answer? – Paul Hoffer Aug 15 '10 at 01:16
  • 1
    Thanks :-) And yes, it is encouraged (see http://meta.stackexchange.com/questions/19448/etiquette-for-selecting-answers ) – Marc-André Lafortune Aug 15 '10 at 14:18
  • I noticed your edit removing mention of 1.8.8. Is it still available in 1.8-head, and you're just editing the question because 1.8.8 won't happen? – Andrew Grimm May 24 '11 at 23:22
  • 3
    @Andrew: Yes, I edited my answer because 1.8.8 won't happen. It should still be in 1.8-head, but that branch is dead :-( – Marc-André Lafortune May 24 '11 at 23:27
  • .sample is such an non obvious method name. I loved choice much better. Change it back Ruby developers! – Henley Dec 28 '12 at 01:36
  • Conveniently, you can also use `sample` on an `ActiveRecord::Relation`; e.g. `@joe.pencils.sample` will randomly choose a writing implement from Joe's pencil collection (assuming normal Rails stuff here). – Purplejacket Dec 22 '13 at 05:49
  • @Purplejacket: Yes, but it might not be the best way to do this. `ActiveRecord::Relation` will delegate the call to an array, so it will load all the records and then pick one randomly. – Marc-André Lafortune Dec 23 '13 at 03:30
  • @Marc-AndréLafortune: that is an excellent point!! A more optimized approach might be some inline SQL combined with this: http://stackoverflow.com/questions/580639/how-to-randomly-select-rows-in-sql – Purplejacket Dec 23 '13 at 04:38
  • I keep getting back here... – Koen. Feb 25 '16 at 13:30
96

myArray.sample(x) can also help you to get x random elements from the array.

benjiman
  • 3,578
  • 4
  • 27
  • 42
beesasoh
  • 1,975
  • 1
  • 13
  • 17
19
myArray.sample

will return 1 random value.

myArray.shuffle.first

will also return 1 random value.

Redithion
  • 956
  • 1
  • 18
  • 31
JJ21
  • 251
  • 2
  • 2
17

Random Number of Random Items from an Array

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

Examples of possible results:

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

=> ["two", "three"]
=> ["one", "three", "two"]
=> ["two"]
Community
  • 1
  • 1
Mike Rapadas
  • 4,533
  • 2
  • 27
  • 21
1
arr = [1,9,5,2,4,9,5,8,7,9,0,8,2,7,5,8,0,2,9]
arr[rand(arr.count)]

This will return a random element from array.

If You will use the line mentioned below

arr[1+rand(arr.count)]

then in some cases it will return 0 or nil value.

The line mentioned below

rand(number)

always return the value from 0 to number-1.

If we use

1+rand(number)

then it may return number and arr[number] contains no element.

-8
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