# Array.shuffle/Array.shuffle!

This works but I can’t escape the nagging sense that there’s a more
concise approach (for one thing, it looks like there are way too
transient objects to me).

Anyone have a better idea?

class Array

def shuffle
t_self = self.dup
t_size = self.size
result=[]
t_size.times { result << t_self.slice!(rand(t_self.size)) }
result
end

def shuffle!
t_self = self.dup
t_size = self.size
self.clear
t_size.times { self << t_self.slice!(rand(t_self.size)) }
self
end

end

Regards…

Jeff M. wrote:

This works but I can’t escape the nagging sense that there’s a more
concise approach (for one thing, it looks like there are way too
transient objects to me).

Anyone have a better idea?

ary2 = ary.sort_by { rand }

Tim H. wrote:

Jeff M. wrote:

This works but I can’t escape the nagging sense that there’s a more
concise approach (for one thing, it looks like there are way too
transient objects to me).

Anyone have a better idea?

ary2 = ary.sort_by { rand }

“Gone in 60 seconds”…

Thanks

Jeff M. wrote:

This works but I can’t escape the nagging sense that there’s a more
concise approach (for one thing, it looks like there are way too
transient objects to me).

Anyone have a better idea?

class Array

def shuffle
t_self = self.dup
t_size = self.size
result=[]
t_size.times { result << t_self.slice!(rand(t_self.size)) }
result
end

def shuffle!
t_self = self.dup
t_size = self.size
self.clear
t_size.times { self << t_self.slice!(rand(t_self.size)) }
self
end

end

Regards…

If you need a less predictable one than the sort_by { rand } then I
suggest this:

class Array

# Shuffle the array

def shuffle!
n = length
for i in 0…n
r = Kernel.rand(n-i)+i
self[r], self[i] = self[i], self[r]
end
self
end

# Return a shuffled copy of the array

def shuffle
dup.shuffle!
end
end

This shuffle is known as fisher-yates/knuth shuffle and is afaik by
current means considered impossible to predict. Also its complexity is
O(n) compared to the O(nlogn) of sort_by (which for many cases probably
still is faster in ruby since it runs mainly in C, I didn’t bench it,
though).

As of 1.8.7 you have those methods already natively provided by ruby.

Regards
Stefan (apeiros)

On Sun Aug 24 19:17:11 2008, Stefan R. wrote:

which for many cases probably still is faster in ruby since it runs
mainly in C, I didn’t bench it, though

Seems youâ€™re right:

Rehearsal -------------------------------------------------------
Knuth: 10.900000 0.000000 10.900000 ( 10.902161)
Sort by #{rand}: 11.050000 0.000000 11.050000 ( 11.060635)
--------------------------------------------- total: 21.950000sec

``````                      user     system      total        real
``````

Knuth: 10.930000 0.020000 10.950000 ( 10.946718)
Sort by #{rand}: 11.020000 0.000000 11.020000 ( 11.020902)

require ‘benchmark’

class Array

# Shuffle the array

def shuffle!
n = length
for i in 0…n
r = Kernel.rand(n-i)+i
self[r], self[i] = self[i], self[r]
end
self
end

# Return a shuffled copy of the array

def shuffle
dup.shuffle!
end
end

n = 500

a = (1…10000).map { rand }
Benchmark.bmbm(20) do |x|
x.report(“Knuth:”) { n.times { a.shuffle } }
x.report(‘Sort by #{rand}:’) { n.times { a.sort_by { rand } } }
end

As of 1.8.7 you have those methods already natively provided by ruby.

Regards
Stefan (apeiros)

Ah! If only the Ubuntu/Debian promotion cycle for Ruby out paced
continental drift…

Thanks again…

I appreciate it.

No, ‘I’ is next in line. “Irresponsible Irmin”

Joel VanderWerf wrote:

Jeff M. wrote:

Ah! If only the Ubuntu/Debian promotion cycle for Ruby out paced
continental drift…

I heard the 9.04 release will be called Galloping Gondwanaland.

Jeff M. wrote:

Ah! If only the Ubuntu/Debian promotion cycle for Ruby out paced
continental drift…

I heard the 9.04 release will be called Galloping Gondwanaland.