66 votes

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

Je me demande s’il est possible de créer un tableau à deux dimensions et d’accéder rapidement à tout sous-tableau horizontal ou vertical qu’il contient.

Je crois 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 pour autant que je sache, nous ne pouvons pas y accéder comme ceci:

 x[3..8][6]
 

Comment puis-je éviter ou pirater cette limite?

93voto

johannes Points 3878

Il y a quelques problèmes avec les 2 dimensions Arrays de la façon dont vous les mettre 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 le multi dimensionnelle Arrays

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

Ceci a l'avantage, que vous n'avez 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 Hash n'est pas trop grand.

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

a= Hash.new(0)

Alors maintenant, sur la façon d'obtenir des sous-tableaux

(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 à partir d'un Hash est presque O(1), de sorte que la collecte s'exécute dans près de O(n). Il y a maintenant moyen de le rendre plus rapide que O(n), que la copie de n éléments est toujours en O(n).

Hashes peut y avoir des problèmes quand ils sont trop gros. Donc, je pense que deux fois sur la mise en œuvre multidimensionnelle Array aime cela, si je savais que ma quantité de données est prise en gros.

31voto

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

En ce qui concerne l’accès aux éléments, cet article est très utile pour une méthode pas à pas pour encapsuler un tableau comme vous le souhaitez:

Comment ruby array

30voto

Vous n'avez pas indiqué votre objectif réel, mais peut-être que cela peut 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 à celle que vous désirez:

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

10voto

Mark Essel Points 1082

Voici un cas de tableau 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] ou 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: