Forum: Italian Ruby user group Array multidimensionale

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Giampiero Z. (Guest)
on 2009-05-14 13:56
ciao a tutti
intanto ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
ho uno strano comportamento su un array a 2 dimensioni;
mi spiego con un esempio:
v = []
v.fill([],0..2)
v.map {|e| e.fill(0,0..2)}
p v
v[1][1] = "XXXX"
p v
produce
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, "XXXX", 0], [0, "XXXX", 0], [0, "XXXX", 0]]
ora, quello che vorrei ottenere invece è
[[0, 0, 0], [0, "XXXX", 0], [0, 0, 0]]
cosa sbaglio?
grazie fin da ora per le risposte
Davide Monfrecola (Guest)
on 2009-05-14 14:01
(Received via mailing list)
2009/5/14 Giampiero Z. <removed_email_address@domain.invalid>:
> p v
> produce
> [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
> [[0, "XXXX", 0], [0, "XXXX", 0], [0, "XXXX", 0]]
> ora, quello che vorrei ottenere invece è
> [[0, 0, 0], [0, "XXXX", 0], [0, 0, 0]]
> cosa sbaglio?
> grazie fin da ora per le risposte

Il problema è nel secondo elemento tutti gli elementi puntano allo stesso
Array.
Prova con:
v = Array.new(2) {Array.new(0)}
In questo modo ogni volta che inserisci un elemento crea un Array
nuovo e non punta allo stesso array.
Penso sia questo il problema, ma poi magari mi sbaglio! :)
Giampiero Z. (Guest)
on 2009-05-14 14:39
Davide Monfrecola wrote:

> Il problema � nel secondo elemento tutti gli elementi puntano allo stesso
> Array.
> Prova con:
> v = Array.new(2) {Array.new(0)}
> In questo modo ogni volta che inserisci un elemento crea un Array
> nuovo e non punta allo stesso array.
> Penso sia questo il problema, ma poi magari mi sbaglio! :)

ciao Davide e grazie per la risposta
in effetti mi sa che hai ragione anche se non capisco fino in fondo...
comunque, seguendo il tuo consiglio, ho modificato come segue e ora
funziona
v = Array.new(3) {Array.new(3) {0}}
p v
v[1][1] = 'XXXX'
p v
produce
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, "XXXX", 0], [0, 0, 0]]
Andrea L. (Guest)
on 2009-05-17 16:14
> in effetti mi sa che hai ragione anche se non capisco fino in fondo...

Non so se sia utile a chiarire i tuoi ultimi dubbi, ma quando scrivo
v=[]
v.fill(Array.new, 0..2)

sto riempiendo v con degli elementi che puntano tutti allo stesso array.
Quando  modifico un elemento qualisasi di v vengono modificati di
conseguenza anche tutti gli altri.
Posso verificare l'esattezza di quanto dico controllando l'object_id
degli elementi:
v.each{|e| puts e.object_id}

che risulteranno tutti uguali (puntano quindi tutti allo stesso oggetto)

Se poi scrivo
v.map{|arr| arr.fill(0, 0..2)}

sto facendo un lavoro inutile in quanto la ricorsione modifica sempre lo
stesso oggetto.
Basterebbe un semplice
v[0].fill(0, 0..2)

per modificare tutti gli elementi dell'array, senza scomodare la
ricorsione.

A questo punto dovrebbe essere chiaro che scrivere
v[1][1] = 'xxx'

modificherà non solo v[1][1], ma anche v[0][1] e v[2][1] poiche' v[0],
v[1], v[2] sono lo stesso oggetto.

Per ottenere quello che avevi in mente tu invece avrei dovuto
inizializzare v così:

v= Array.new(3){[]}
v.map ...
...

infatti ora
v.each{|e| puts e.object_id}

restituisce valori diversi, quindi ogni elemento punta ad un array
diverso.
Giampiero Z. (Guest)
on 2009-05-19 11:01
Andrea L. wrote:
>> in effetti mi sa che hai ragione anche se non capisco fino in fondo...
>
> Non so se sia utile a chiarire i tuoi ultimi dubbi, ma quando scrivo
> v=[]
> v.fill(Array.new, 0..2)
>
> sto riempiendo v con degli elementi che puntano tutti allo stesso array.
grazie Andrea
in effetti ora mi è più chiaro
in futuro,quando sicuramente ripeterò l'errore, per lo meno sarò colto
dal dubbio e saprò quale direzione prendere per rimediare
ciao a tutti
This topic is locked and can not be replied to.