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
精彩评论