66 votes

Créer des tableaux à deux dimensions et accéder aux sous-réseaux en Ruby

Je me demande s'il est possible de créer un tableau à deux dimensions et d'accéder rapidement à n'importe quel sous tableau horizontal ou vertical dans ce tableau ?

Je pense que nous pouvons accéder à un sous tableau horizontal dans le cas suivant :

x = Array.new(10) { Array.new(20) }

x[6][3..8] = 'something'

Mais d'après ce que j'ai compris, nous ne pouvons pas y accéder de cette manière :

x[3..8][6]

Comment puis-je éviter ou contourner cette limite ?

95voto

johannes Points 3878

Il y a quelques problèmes avec le système bidimensionnel Arrays la façon dont vous les mettez en œuvre.

a= [[1,2],[3,4]]
a[0][2]= 5 # works
a[2][0]= 6 # error

Hash comme Array

Je préfère utiliser Hashes pour un système multidimensionnel Arrays

a= Hash.new
a[[1,2]]= 23
a[[5,6]]= 42

L'avantage est que vous ne devez pas créer manuellement des colonnes ou des lignes. L'insertion dans les hachages est presque O(1), donc il n'y a pas d'inconvénient ici, aussi longtemps que votre fichier Hash ne devienne pas trop grande.

Vous pouvez même définir une valeur par défaut pour tous les éléments non spécifiés.

a= Hash.new(0)

Maintenant, comment obtenir des sous-réseaux ?

(3..5).to_a.product([2]).collect { |index| a[index] }
[2].product((3..5).to_a).collect { |index| a[index] }

(a..b).to_a s'exécute en O(n). La récupération d'un élément d'un Hash est presque O(1), donc la collecte s'exécute en presque O(n). Il n'y a aucun moyen de le rendre plus rapide que O(n), car copier n éléments est toujours O(n).

Hashes peuvent avoir des problèmes lorsqu'ils deviennent trop gros. J'y réfléchirais donc à deux fois avant de mettre en place un système multidimensionnel. Array comme ça, si je savais que ma quantité de données devient grande.

32voto

shawnjan Points 494
rows, cols = x,y  # your values
grid = Array.new(rows) { Array.new(cols) }

Pour ce qui est de l'accès aux éléments, cet article est assez bon pour expliquer pas à pas comment encapsuler un tableau comme vous le souhaitez :

Comment faire un tableau en ruby

30voto

Vous n'avez pas indiqué votre objectif réel, mais peut-être que ceci peut vous aider :

require 'matrix'  # bundled with Ruby
m = Matrix[
 [1, 2, 3],
 [4, 5, 6]
]

m.column(0) # ==> Vector[1, 4]

(et les vecteurs agissent comme des tableaux)

ou, en utilisant une notation similaire, comme vous le souhaitez :

m.minor(0..1, 2..2) # => Matrix[[3], [6]]

11voto

Mark Essel Points 1082

Voici un cas de réseau 3D

class Array3D
   def initialize(d1,d2,d3)
    @data = Array.new(d1) { Array.new(d2) { Array.new(d3) } }
   end

  def [](x, y, z)
    @data[x][y][z]
  end

  def []=(x, y, z, value)
    @data[x][y][z] = value
  end
end

Vous pouvez accéder aux sous-sections de chaque tableau comme n'importe quel autre tableau Ruby. @data[0..2][3..5][8..10] = 0 etc

5voto

pierr Points 9148

x.transpose[6][3..8] o x[3..8].map {|r| r [6]} donnerait ce que vous voulez.

Exemple :

a = [ [1,  2,  3,  4,  5],
      [6,  7,  8,  9,  10],
      [11, 12, 13, 14, 15],
      [21, 22, 23, 24, 25]
    ]

#a[1..2][2]  -> [8,13]
puts a.transpose[2][1..2].inspect   # [8,13]
puts a[1..2].map {|r| r[2]}.inspect  # [8,13]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X