New to Ruby: copying arrays?

J

John Park

Hi. First-time poster here. I've done some programming in Delphi
before (like 10 years ago), and I wanted to get back to programming as a
hobby. I've looked at several languages, and Ruby looked the funnest.
:) So here I am.

For my first project, I've decided to make a Sudoku class, making it
general enough so that it can easily be subclassed to implement many
Sudoku variations out there.

To store the board state, I decided to make an instance variable @board
which is a two-dimensional array of 9x9. And there would be several
methods that will manipulate the board.

Then it occurred to me that it would be nice to have a .revert method
that will revert the board to its initial state.

Easy enough, I thought.

To the .initialize method, I added the line:

@initialboard = @board

and I added a new .revert method which did:

@board = @initialboard

And this, as you Ruby-experts may imagine, is where I came to
face-to-face with Ruby's "variables are references, not containers"
nature. Every time I manipulated @board, the "content" of @initialboard
would get altered as well, making it useless as a backup of the initial
state of the board.

I've tried .dup and .clone methods, but it didn't work because @board
was a two-dimensional, array-within-array structure. .dup and .clone
methods only duplicated the top level array, and the sub-level arrays
were still being referenced to the same data, leading to the same result
as the first time around.

So here's my question. Is there a simple and elegant way to duplicate
the entire content of a multi-dimensional array?

Right now, the only workarounds I can think of are: 1) store the data in
one long one-dimensional array, of 2) use an iterator to duplicate each
sub-level arrays individually. Neither are very elegant nor attractive.
:(

Thanks in advance to any insight you guys can give me in this matter.



Oh, one more question: what's the difference between .dup and .clone
methods?
 
S

Stefano Crocco

Alle Sunday 28 December 2008, John Park ha scritto:
So here's my question. =C2=A0Is there a simple and elegant way to duplica= te
the entire content of a multi-dimensional array?

You can use Marshal.dump and Marshal.load:

a =3D [["a", "b"],["c", "d"]]
b =3D Marshal.load(Marshal.dump(a))
a[0][0].upcase!
puts a[0][0] #=3D> A
puts b[0][0] #=3D> a

Note that this only works if your array only contains serializable objects =
(in=20
particular, it should not contain method or proc objects, IO objects and=20
singleton objects). See the documentation for the Marshal module for more=20
information (using the command ri marshal).
Oh, one more question: what's the difference between .dup and .clone
methods?

As far as I know, the only difference is that clone also copies the frozen=
=20
state of the original object, while dup doesn't:
s1 =3D "test"
s1.freeze
s2 =3D s1.dup
s3 =3D s1.clone
puts s2.frozen? #=3D> false
puts s3.frozen? #=3D> true

I hope this helps

Stefano
 
J

John Park

Stefano said:
You can use Marshal.dump and Marshal.load:

a = [["a", "b"],["c", "d"]]
b = Marshal.load(Marshal.dump(a))
a[0][0].upcase!
puts a[0][0] #=> A
puts b[0][0] #=> a

Just experimented with it in irb. Awesome! Exactly what I was hoping
for!

Thanks for the super-quick response! :)
 
S

Simon Krahnke

* John Park said:
Hi. First-time poster here. I've done some programming in Delphi
before (like 10 years ago), and I wanted to get back to programming as a
hobby. I've looked at several languages, and Ruby looked the funnest.
:) So here I am.
Cool.

To store the board state, I decided to make an instance variable @board
which is a two-dimensional array of 9x9. And there would be several
methods that will manipulate the board.

Why do you want to do that? A standard Sudoku consists of 81 cells that
ordered in three different ways. Why prefer one order by your picking of
coordinates?
Right now, the only workarounds I can think of are: 1) store the data in
one long one-dimensional array,

That's what I did.

mfg, simon .... l
 
J

James Gray

Alle Sunday 28 December 2008, John Park ha scritto:

As far as I know, the only difference is that clone also copies the
frozen
state of the original object, while dup doesn't:
s1 = "test"
s1.freeze
s2 = s1.dup
s3 = s1.clone
puts s2.frozen? #=> false
puts s3.frozen? #=> true

clone() also copies an object's singleton class:
NoMethodError: undefined method `speak' for "cat":String
from (irb):4=> "purr"

I learned this and other great things from these screencasts:

http://www.pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming

James Edward Gray II
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top