Bagaimana cara mengurutkan (scramble) array secara acak di Ruby?


128

Saya ingin item array saya diacak. Sesuatu seperti ini:

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

dan seterusnya, secara acak

Jawaban:


293

Dibangun sekarang:

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

3
Dan jika Anda ingin menerapkannya sendiri: en.wikipedia.org/wiki/Fisher-Yates_shuffle
Joey

Atau jika Anda menginginkannya untuk Ruby <1.9: memerlukan 'backports'
Marc-André Lafortune

1
Sepertinya itu ada di Ruby 1.8.7 juga.
Brian Armstrong

Benar-benar luar biasa.
sidney

1
Hanya ingin menambahkan: jika Anda ingin memengaruhi koleksi, tambahkan !setelah panggilan untuk mengacak. Tanpa !array shuffled dikembalikan, dan matang untuk tugas.
Muyiwa Olu

27

Untuk ruby ​​1.8.6 (yang tidak memiliki shuffle bawaan):

array.sort_by { rand }

11
@Josh: Halaman yang Anda tautkan menjelaskan algoritma yang sama sekali berbeda. Perhatikan bahwa sort_byfungsi ruby tidak berfungsi seperti fungsi sortir javascript (atau fungsi sortir ruby ​​dalam hal ini), yang hanya peduli apakah angka yang dihitung kurang dari nol, nol atau lebih besar dari nol. Alih-alih sort_bymengingat nilai yang dihitung untuk setiap item dan kemudian mengurutkan item dengan nilai itu. Jadi dalam hal ini setiap item diberi nomor acak dan kemudian array diurutkan berdasarkan angka-angka acak itu.
sepp2k

Dengan array ukuran besar jenis ini dengan angka acak untuk setiap item mungkin memakan waktu terlalu lama (O (NLogN), kita bisa melakukannya dalam waktu linier jika kita menghasilkan angka acak dari item sebelumnya yang telah kita kocok dan lalu tukar sebagai iterator increment
Downhillski

9

Untuk ruby ​​1.8.6 sebagai contoh sepp2k, tetapi Anda tetap ingin menggunakan metode "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]

Bersulang


2

Kode dari Gem Backports hanya untuk Array untuk Ruby 1.8.6. Ruby 1.8.7 atau lebih tinggi sudah ada di dalamnya.

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

0

The Ruby Aspek perpustakaan ekstensi memiliki Randommodul yang menyediakan metode yang berguna termasuk shuffledan shuffle!untuk sekelompok kelas inti termasuk Array, Hashdan String.

Berhati-hatilah jika Anda menggunakan Rails karena saya mengalami beberapa bentrokan yang tidak menyenangkan dalam cara monkeypatchingnya berbenturan dengan Rails ...

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.