# New to Ruby: copying arrays?

**URL:** <https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464>\
**Category:** Ruby\
**Created:** [December 28, 2008, 11:51am UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464 "2008-12-28T11:51:15Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 11:51am UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/1 "2008-12-28T11:51:15Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 12:03pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/2 "2008-12-28T12:03:19Z")

</div>

Alle Sunday 28 December 2008, John P. ha scritto:

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

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

Note that this only works if your array only contains serializable  
objects (in  
particular, it should not contain method or proc objects, IO objects and  
singleton objects). See the documentation for the Marshal module for  
more  
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  
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

I hope this helps

Stefano

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 12:20pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/3 "2008-12-28T12:20:23Z")

</div>

Stefano C. wrote:

> 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! 🙂

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 1:02pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/4 "2008-12-28T13:02:31Z")

</div>

Stefano C. wrote:

> b = Marshal.load(Marshal.dump(a))

A clever compiler would optimise that to

b = a

(But I don’t suppose Ruby does!)

Dave

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 4:35pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/5 "2008-12-28T16:35:51Z")

</div>

- John P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) (11:50) schrieb:

> 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

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 6:26pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/6 "2008-12-28T18:26:51Z")

</div>

On Dec 28, 2008, at 5:02 AM, Stefano C. wrote:

> s3 = s1.clone  
> puts s2.frozen? #=\> false  
> puts s3.frozen? #=\> true

clone() also copies an object’s singleton class:

> > s = “cat”  
> > =\> “cat”  
> > def s.speak; “purr” end  
> > =\> nil  
> > s.speak  
> > =\> “purr”  
> > s.dup.speak  
> > NoMethodError: undefined method `speak’ for “cat”:String  
> > from (irb):4  
> > s.clone.speak  
> > =\> “purr”

I learned this and other great things from these screencasts:

[Pragmatic Bookshelf: By Developers, For Developers](http://www.pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming)

James Edward G. II

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 1:15pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/7 "2008-12-28T13:15:59Z")

</div>

On 28.12.2008 13:02, Dave B. wrote:

> Stefano C. wrote:
> 
> > b = Marshal.load(Marshal.dump(a))
> 
> A clever compiler would optimise that to
> 
> b = a

That would be a broken compiler.

robert

---

<div class="post-metadata">

**Author:** ![johnpetterson](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/41988e/32.png) [@johnpetterson](https://www.ruby-forum.com/u/johnpetterson)\
**Post date:** [December 28, 2008, 10:27pm UTC](https://www.ruby-forum.com/t/new-to-ruby-copying-arrays/156464/8 "2008-12-28T22:27:44Z")

</div>

John P.:

> Stefano C. wrote:

> > 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!

To extend on the above, what I would do would be to create a separate  
Board class to represent your Sudoku board, rather than directly using  
Array for this.

First, you can then implement it in various ways, and (as long as you  
maintain the same methods to access and opearte on it) it would be  
transparent to the Sudoku solver whether your Board is implemented  
as an Array of three three-element Arrays, a nine-element â€˜flatâ€™  
Array, or anything else (say, maybe 27 Sets containing 81 elements  
in non-disjoint groups of nines?).

Second, you can then have

class Board  
def dup  
Marshal.load Marshal.dump(self)  
end  
end

(which is an idiom I use extensively in my code) and simply use

@initialboard = @board.dup  
â€¦  
@board = @initialboard.dup

in your solver. 🙂

– Shot
