开发者

How can I shuffle an array/hash in Ruby?

For learning purposes, what is this called? Is the object being created an array or a hash?

stack_of_cards = []

This is how I'm filling it:

stack_of_cards << Card.new("A", "Spades", 1)
stac开发者_如何学运维k_of_cards << Card.new("2", "Spades", 2)
stack_of_cards << Card.new("3", "Spades", 3)
...

Here is my Card class:

class Card

  attr_accessor :number, :suit, :value

  def initialize(number, suit, value)
    @number = number
    @suit = suit
    @value = value
  end

  def to_s
    "#{@number} of #{@suit}"
  end
end

I'd like to shuffle the elements in this array/hash (what is this called? :S)

Any suggestions?


stack_of_cards.shuffle

It is an Array, see http://www.ruby-doc.org/core-1.8.7/classes/Array.html for more information.

I've written the functional form, which returns a new Array, and it's the new one that's shuffled. You can instead use:

stack_of_cards.shuffle!

...to shuffle the array in-place.


If you want to shuffle a hash you can use something like this:

class Hash
  def shuffle
    Hash[self.to_a.sample(self.length)]
  end

  def shuffle!
    self.replace(self.shuffle)
  end
end

I've posted this answer since I always find this question if I search for "ruby shuffle hash".


In addition to using the shuffle method, you can use the sort method:

array.sort {|a, b| rand <=> rand }

This may be of use if you are using an older version of Ruby where shuffle is not implemented. As with shuffle!, you can use sort! to work on the existing array.


If you wanted to get crazy and write your own in-place shuffle method, you could do something like this.

 def shuffle_me(array)
   (array.size-1).downto(1) do |i|
     j = rand(i+1)
     array[i], array[j] = array[j], array[i]
   end

   array
 end 


For arrays:

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

For hashes:

Hash[*hash.to_a.shuffle.flatten]
Hash[*{a: 1, b: 2, c: 3}.to_a.shuffle.flatten(1)]
#=> {:b=>2, :c=>3, :a=>1}
#=> {:c=>3, :a=>1, :b=>2}
#=> {:a=>1, :b=>2, :c=>3}
# Also works for hashes containing arrays
Hash[*{a: [1, 2], b: [2, 3], c: [3, 4]}.to_a.shuffle.flatten(1)]
#=> {:b=>2, :c=>3, :a=>1}
#=> {:c=>[3, 4], :a=>[1, 2], :b=>[2, 3]}


Old question, but maybe help for someone else. I used it to create a card game, that's what @davissp14 wrote, it's called "Fisher-Yates algorithm"

module FisherYates

  def self.shuffle(numbers)
    n = numbers.length
    while n > 0 
      x = rand(n-=1)
      numbers[x], numbers[n] = numbers[n], numbers[x]
    end
    return numbers
  end

end 

Now you can use it as:

numbers_array = [1,2,3,4,5,6,7,8,9]
asnwer = FisherYates.shuffle(numbers_array)
return answer.inspect

https://dev.to/linuxander/fisher-yates-shuffle-with-ruby-1p7h


If you want to shuffle a hash, but don't want to overload the Hash class, you can use the sort function and then convert it back to a hash with the to_h function (Ruby 2.1+):

a = {"a" => 1, "b" => 2, "c" => 3}
puts a.inspect
a = a.sort {|a, b| rand <=> rand }.to_h
puts a.inspect


For an array:

array.shuffle

For a hash:

hash.sort_by{ rand() }


An alternative hash shuffle is ..

hash.to_a.shuffle.to_h
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜