138

I'd like to have my array items scrambled. Something like this:

[1,2,3,4].scramble => [2,1,3,4]
[1,2,3,4].scramble => [3,1,2,4]
[1,2,3,4].scramble => [4,2,3,1]

and so on, randomly

Mike Atlas
  • 8,193
  • 4
  • 46
  • 62
Daniel Cukier
  • 11,502
  • 15
  • 68
  • 123

5 Answers5

316

Built in now:

[1,2,3,4].shuffle => [2, 1, 3, 4]
[1,2,3,4].shuffle => [1, 3, 2, 4]
Ron Gejman
  • 6,135
  • 3
  • 25
  • 34
28

For ruby 1.8.6 (which does not have shuffle built in):

array.sort_by { rand }
sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 11
    @Josh: The page you linked to describes an entirely different algorithm. Note that ruby's `sort_by` function does not work like javascript's sort function (or ruby's sort function for that matter), which only cares whether the computed number is less than zero, zero or greater than zero. Instead `sort_by` remembers the computed value for each item and then sorts the items by that value. So in this case each item is assigned a random number and then the array is sorted by those random numbers. – sepp2k Sep 05 '11 at 06:09
  • With a large size array this sort by the random numbers for each item might take too long (O(NLogN), we could do it in a linear time if we generate a random number from the previous items we have shuffled and then swap as the iterator increment. – Downhillski Mar 07 '17 at 01:32
8

For ruby 1.8.6 as sepp2k's example, but you still want use "shuffle" method.

class Array
  def shuffle
    sort_by { rand }
  end
end

[1,2,3,4].shuffle #=> [2,4,3,1]
[1,2,3,4].shuffle #=> [4,2,1,3]

cheers

bry4n
  • 327
  • 1
  • 6
3

Code from the Backports Gem for just the Array for Ruby 1.8.6. Ruby 1.8.7 or higher is built in.

class Array
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
  def shuffle
    dup.shuffle!
  end unless method_defined? :shuffle

  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
  def shuffle!
    size.times do |i|
      r = i + Kernel.rand(size - i)
      self[i], self[r] = self[r], self[i]
    end
    self
  end unless method_defined? :shuffle!
end
Vizjerai
  • 1,912
  • 1
  • 24
  • 33
0

The Ruby Facets library of extensions has a Random module which provides useful methods including shuffle and shuffle! to a bunch of core classes including Array, Hash and String.

Just be careful if you're using Rails as I experienced some nasty clashes in the way its monkeypatching clashed with Rails'...

edavey
  • 394
  • 2
  • 2