2010-10-25 6 views
3

Excusez la question de débutant. J'essaye de créer un tableau bidimensionnel dans ruby, et initialise toutes ses valeurs à 1. Mon code crée le tableau bidimensionnel très bien, mais ne parvient pas à modifier ses valeurs. Est-ce que quelqu'un peut expliquer ce que je fais mal?difficulté à modifier tableau de rubis bidimensionnel

def mda(width,height) 
    #make a two dimensional array 
    a = Array.new(width) 
    a.map! { Array.new(height) } 

    #init all its values to 1 
    a.each do |row| 
     row.each do |column| 
      column = 1 
     end 
    end 
    return a 
    end 

Répondre

3

Il la ligne row.each do |column| la column variable est la copie de la valeur row. Vous ne pouvez pas modifier sa valeur de cette manière. Vous devez faire:

def mda(width,height) 
    a = Array.new(width) 
    a.map! { Array.new(height) } 
    a.each do |row| 
    row.map!{1} 
    end 
    return a 
end 

Ou mieux:

def mda(width,height) 
    a = Array.new(width) 
    a.map! { Array.new(height) } 

    a.map do |row| 
    row.map!{1} 
    end 
end 

Ou mieux:

def mda(width,height) 
    a = Array.new(width){ Array.new(height) } 
    a.map do |row| 
    row.map!{1} 
    end 
end 

Ou mieux:

def mda(width,height) 
    Array.new(width) { Array.new(height){1} } 
end 
+0

Est-ce que 'width' et 'height' sont mélangés? En outre, cela peut être fait sans blocs: Array.new (height, Array.new (width, 1)) – steenslag

+0

@steenslag, Non, il ne peut pas. Si vous créez un tableau multidimensionnel de cette manière, lorsque vous affectez une valeur à un élément, il sera étendu à la colonne entière. Ce serait comme 'array = [[1] * w] * h', où vous allez simplement faire des' h' copies du * pointeur * vers le même tableau à 1 dimension. A propos du mélange de 'width' et' height' - c'est une autre question, qui n'était pas censée être discutée par l'auteur. – Nakilon

+0

P.S.: voir la réponse de ghostdog74. Il doit avoir au moins un bloc. – Nakilon

-1

column dans votre boucle each imbriquée est une copie de la valeur à cet endroit dans le tableau, pas un pointeur/référence, donc quand vous changez sa valeur que vous changez seulement la valeur de la copie (qui cesse d'exister en dehors du bloc).

Si vous voulez juste un tableau à deux dimensions peuplé avec quelque chose de 1 aussi simple que cela fonctionnera:

def mda(width,height) 
    [ [1] * width ] * height 
end 

assez simple.


Par ailleurs, si vous voulez savoir comment modifier les éléments d'un tableau à deux dimensions que nous parcourons dessus, voici une façon (à partir de la ligne 6 dans votre code):

#init all its values to 1 
a.length.times do |i| 
    a[i].length.times do |j| 
    a[i][j] = 1 
    end 
end 
+0

Voir les commentaires sur la réponse de Nakilon: cette création de tableau ne ne fonctionne pas (essayez de changer l'une de ses valeurs). – steenslag

1

each passe dans le paramètre de bloc la valeur de chaque élément, et non pas l'élément lui-même, de sorte que column = 1 ne modifie pas réellement le tableau.

Vous pouvez le faire en une seule étape, cependant - voir the API docs pour plus de détails sur les différentes formes de Array#new. Essayez a = Array.new(width) {|i| Array.new(height) {|j| 1 } }

+2

Inutile d'inclure des variables de bloc lorsqu'elles ne sont pas utilisées. –

+0

Je ne le savais pas. Je supposais qu'ils étaient comme des params de méthode, et Ruby se plaindrait s'ils étaient absents. Ah bien - YLSNED! – Chowlett

0

vous pouvez le créer comme ceci?

a=Array.new(width) { Array.new(height,1) } 
Questions connexes