-3

I have this array which I would like to copy and change an element's value. How can I do it (Ruby 1.9.3p429)

a = Array.new(2,"test")   #a => ["test","test"] #a.object_id => 21519600  #a[0].object_id => 21519612
b = a.clone               #b => ["test","test"] #b.object_id => 22940520  #b[0].object_id => 21519612 
c = a.dup                 #c => ["test","test"] #c.object_id => 22865176  #c[0].object_id => 21519612
d = Array.new(a)          #d => ["test","test"] #c.object_id => 23179224  #d[0].object_id => 21519612

c[0].upcase!  #produces   #a => ["TEST","TEST"], #b => ["TEST","TEST"], #c => ["TEST","TEST"] ...`
Bala
  • 11,068
  • 19
  • 67
  • 120
  • How do you want to change it? – sawa Jul 31 '13 at 13:46
  • I would suggest using map and change it that way. – Martin Larsson Jul 31 '13 at 13:50
  • possible duplicate of [How to create a deep copy of an object in Ruby?](http://stackoverflow.com/questions/8206523/how-to-create-a-deep-copy-of-an-object-in-ruby) – Damien MATHIEU Jul 31 '13 at 13:55
  • @damien: So you expect a ruby beginner to know about Marshal Load/Dump to understand the behaviour of an Array/References from it. – Bala Jul 31 '13 at 14:02
  • @sawa: 1. I was expecting only c[0] to hold upcase, 2. Dup, Clone all gave different object_ids, so I expected they are all different objects to one another. – Bala Jul 31 '13 at 14:04
  • Regarding 2, they (the arrays) are different objects, but the internal strings are shared among them. – sawa Jul 31 '13 at 14:11

2 Answers2

2

In Ruby every object is actually a reference to object so if you have array

x = [a, b, c, d]

and copy it into another array

y = x.clone

it will copy references to original objects, not objects themselves.

To do exactly what you want you would have to copy objects in a loop, however you're too focused on how you want to achieve array copying, instead of achieving your ultimate goal, get a new array which consists of upcased items of the original array.

Explore the Enumerable module and you will find things like #map, #select, #inject, etc. For instance this is how you get a copy of array with all names upcased:

["test", "test"].map { |element| element.upcase }
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
keymone
  • 8,006
  • 1
  • 28
  • 33
0

From your comment, you seem to want to upcase "c[0] only". I don't understand why you need to capitalize via a duplicate of a, but here is how to do it.

a = Array.new(2){"test"}
c = a.dup
c[0].upcase!
a # => ["TEST", "test"]
sawa
  • 165,429
  • 45
  • 277
  • 381
  • There was no specific requirement. My objective was merely to understand these subtleties of ruby. – Bala Jul 31 '13 at 14:17