2009-11-12 5 views
0

Je dois créer une classe de tableau à deux dimensions. Je l'ai fait un travail, mais il a découvert que ma classe a tout simplement un tableau à deux faible intérieure, et pour accéder aux éléments que je dois écrire un mot redondant « table »:Ruby: OOP & tableau à deux dim. Question

class Table 
    attr_accessor :table 
    def initialize(w,h) 
    @table = Array.new(h) 
    h.times do @table << Array.new(w) 
    end 
end 

x = Table.new(10,10) 
x.table[5][6] = 'example' 

et ainsi de suite. L'idée est que je veux écrire seulement x[5][6] à la fois, pour accéder aux éléments. Pour autant que je comprenne, je dois hériter de la classe Array, et l'étendre en quelque sorte pour se comporter comme un tableau à deux dims. Si j'ai raison - comment je fais ça?

Répondre

1

I Pensez cela pourrait être ce que vous cherchez. Il utilise la variable d'instance @table pour suivre le tableau interne, mais n'expose pas un accesseur pour celui-ci. Voici la définition:

class Table 

    def initialize(row_count, column_count) 
    @table = Array.new 

    row_count.times do |index| 
     @table[index] = Array.new(column_count) 
    end 
    end 

    def []=(row, column, value) 
    @table[row][column] = value 
    end 

    def [](row, column = nil) 
    if column.nil? 
     @table[row] 
    else 
     @table[row][column] 
    end 
    end 

    def inspect 
    @table.inspect 
    end 
end 

Et voici comment vous pouvez l'utiliser:

t = Table.new(2, 5) 
t[0,0] = 'first' 
t[1,4] = 'last' 
t[0][1] = 'second' 

puts t[0,0] 
puts t.inspect 

Vous pouvez également jeter un oeil à Ruby's enumerable module plutôt que le sous-classement Array.

0

Y at-il une raison particulière que vous voulez écrire votre propre classe de tableau? Par défaut, vous pouvez dire ensemble ce que pour alimenter les nouveaux éléments avec, en fournissant le second argument:

>> a = Array.new(10, []) 
=> [[], [], [], [], [], [], [], [], [], []] 

Edit: Apparemment, cette façon, il renseigne les tableaux avec des références à objet passé, donc une fois que vous faites a[0][0] = "asd", chaque premier élément de tableaux contenus va changer. Pas cool.

>> a[0][0] = "asd" 
=> "asd" 
>> a 
=> [["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"]] 

Pour avoir chaque tableau contenu soit unique, utilisez la troisième syntaxe, et lui donner un bloc pour exécuter chaque fois - le résultat du bloc sera utilisé pour remplir le tableau:

>> b = Array.new(10) { [] } 
=> [[], [], [], [], [], [], [], [], [], []] 
>> b[0][0] = "asd" 
=> "asd" 
>> b 
=> [["asd"], [], [], [], [], [], [], [], [], []] 

en outre, en raison des réseaux de rubis façon de travailler, de définir la taille de l'axe y est même pas nécessaire:

>> a = Array.new(5) 
=> [nil, nil, nil, nil, nil] 
>> a[10] 
=> nil 
>> a[10] = "asd" 
=> "asd" 
>> a 
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "asd"] 

le tableau est étendu automatiquement lorsque vous mettez quelque chose dans l'index qui est plus grande que la taille actuelle. Donc, faites juste un tableau contenant dix tableaux vides, et vous avez un tableau de taille 10 * n prêt à l'emploi.

+0

Oui, je veux vraiment créer une classe pour séparer ses routages internes (c'est-à-dire les méthodes) de la logique de l'algorithme actuel, sur lequel je travaille maintenant. Merci pour le redimensionnement automatique des tableaux! Je ne savais pas que – gmile