¿Cómo ordenar aleatoriamente (codificar) una matriz en Ruby?

128

Me gustaría mezclar mis elementos de la matriz. Algo como esto:

[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]

y así sucesivamente, al azar

Daniel Cukier
fuente

Respuestas:

293

Construido ahora:

[1,2,3,4].shuffle => [2, 1, 3, 4]
[1,2,3,4].shuffle => [1, 3, 2, 4]
Ron Gejman
fuente
3
Y si desea implementarlo usted mismo: en.wikipedia.org/wiki/Fisher-Yates_shuffle
Joey el
O si lo desea para Ruby <1.9: requiere 'backports'
Marc-André Lafortune
1
Parece que también está en Ruby 1.8.7.
Brian Armstrong
Eso es completamente asombroso.
sidney
1
Solo quería agregar: si desea afectar la colección, agregue un !después de la llamada para barajar. Sin el, !la matriz aleatoria se devuelve, y madura para una asignación.
Muyiwa Olu
27

Para ruby ​​1.8.6 (que no tiene shuffle incorporado):

array.sort_by { rand }
sepp2k
fuente
11
@ Josh: la página a la que se vinculó describe un algoritmo completamente diferente. Tenga en cuenta que la sort_byfunción de ruby no funciona como la función de clasificación de javascript (o la función de clasificación de ruby ​​para el caso), que solo le importa si el número calculado es menor que cero, cero o mayor que cero. En su lugar, sort_byrecuerda el valor calculado para cada elemento y luego ordena los elementos por ese valor. En este caso, a cada elemento se le asigna un número aleatorio y luego la matriz se ordena por esos números aleatorios.
sepp2k
Con una matriz de gran tamaño, este orden por los números aleatorios para cada elemento puede llevar demasiado tiempo (O (NLogN), podríamos hacerlo en un tiempo lineal si generamos un número aleatorio a partir de los elementos anteriores que hemos barajado y luego cambiamos como incremento del iterador.
Downhillski
9

Para ruby ​​1.8.6 como ejemplo de sepp2k, pero aún desea utilizar el método "shuffle".

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]

salud

bry4n
fuente
2

Código de Backports Gem solo para Array for Ruby 1.8.6. Ruby 1.8.7 o superior está integrado.

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
fuente
0

La biblioteca de extensiones Ruby Facets tiene un Randommódulo que proporciona métodos útiles que incluyen shuffley shuffle!para un grupo de clases principales que incluyen Array, Hashy String.

Solo tenga cuidado si está usando Rails, ya que experimenté algunos desagradables enfrentamientos en la forma en que su parche chocó con el de Rails ...

edavey
fuente