Array multidimensionale


#1

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


#2

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


#3

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

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


#4

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.


#5

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