web-dev-qa-db-fra.com

Tableau multidimensionnel Ruby

C'est peut-être le problème qui vient de mon manque de capacité à trouver des éléments ici, mais je ne trouve rien sur la création de tableaux multidimensionnels dans Ruby.

Quelqu'un pourrait-il s'il vous plaît me donner un exemple sur la façon de le faire? 

41
andkjaer

Strictement parlant, il n’est pas possible de créer des tableaux multidimensionnels en Ruby. Mais il est possible de placer un tableau dans un autre tableau, qui est presque identique à un tableau multidimensionnel.

Voici comment créer un tableau 2D en Ruby:

a = [[1,2,3], [4,5,6], [7,8,9]]


Comme indiqué dans les commentaires, vous pouvez également utiliser NArray , qui est une bibliothèque de tableaux numériques Ruby:

require 'narray'
b = NArray[ [1,2,3], [4,5,6], [7,8,9] ]

Utilisez a[i][j] pour accéder aux éléments du tableau. De manière générale, a[i] renvoie le "sous-tableau" stocké à la position i sur a. Ainsi, a[i][j] renvoie le numéro d'élément j à partir du tableau stocké à la position i.

40
Veger

vous pouvez passer un bloc à Array.new

Array.new(n) {Array.new(n,default_value)}

la valeur qui retourne le bloc sera la valeur de chaque index du premier tableau, 

alors.. 

Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]

et vous pouvez accéder à ce tableau en utilisant array[x][y]

également pour la deuxième instanciation de tableau, vous pouvez également passer un bloc comme valeur par défaut. alors

Array.new(2) { Array.new(3) { |index| index ** 2} } #=> [[0, 1, 4], [0, 1, 4]]
22
Orlando

Juste une clarification:

arr = Array.new(2) {Array.new(2,5)} #=> [[5,5],[5,5]]

n'est pas du tout la même chose que:

arr = Array.new(2, Array.new(2, 5))

dans le dernier cas, essayez:

arr[0][0] = 99

et voici ce que vous avez:

[[99,5], [99,5]]
6
Xavier Nayrac

La méthode donnée ci-dessus ne fonctionne pas.

n = 10
arr = Array.new(n, Array.new(n, Array.new(n,0.0))) 
arr[0][1][2] += 1
puts arr[0][2][2]

est équivalent à

n = 10
a = Array.new(n,0.0)
b = Array.new(n,a)
arr = Array.new(n, b) 
arr[0][1][2] += 1
puts arr[0][2][2]

et affichera 1.0, pas 0.0, car nous modifions le tableau a et imprimons l’élément du tableau a.

3
kipar

Il existe deux façons d’initialiser un tableau multiple (taille de 2) . Toutes les autres réponses montrent des exemples avec une valeur par défaut.

Déclarez chaque sous-tableau (vous pouvez le faire dans un runtime):

multi = []
multi[0] = []
multi[1] = []

ou déclarer la taille d'un tableau parent lors de l'initialisation:

multi = Array.new(2) { Array.new }

Exemple d'utilisation:

multi[0][0] = 'a'
multi[0][1] = 'b'
multi[1][0] = 'c'
multi[1][1] = 'd'

p multi # [["a", "b"], ["c", "d"]]
p multi[1][0] # "c"

Donc, vous pouvez envelopper la première manière et l'utiliser comme ceci:

@multi = []
def multi(x, y, value)
   @multi[x] ||= []
   @multi[x][y] = value
end

multi(0, 0, 'a')
multi(0, 1, 'b')
multi(1, 0, 'c')
multi(1, 1, 'd')

p @multi # [["a", "b"], ["c", "d"]]
p @multi[1][0] # "c"
3
Evmorov

J'ai dû reproduire récemment un tableau multidimensionnel de style PHP dans Ruby. Voici ce que j'ai fait:

# Produce PHP-style multidimensional array.
#
# Example
#
# arr = Marray.new
#
# arr[1][2][3] = "foo"
# => "foo"
#
# arr[1][2][3]
# => "foo"

class Marray < Array
  def [](i)
    super.nil? ? self[i] = Marray.new : super
  end
end
1
Damian Borowski

En réalité, cela est beaucoup plus rapide que la méthode de bloc donnée ci-dessus:

arr = Array.new(n, Array.new(n, Array.new(n,0.0))) 

arr[0][1][2] += 1
1
Kri-ban

Voici une implémentation d'une classe de tableau 3D en Ruby, dans ce cas la valeur par défaut est 0

class Array3
 def initialize
   @store = [[[]]]
 end

 def [](a,b,c)
  if @store[a]==nil ||
    @store[a][b]==nil ||
    @store[a][b][c]==nil
   return 0
  else
   return @store[a][b][c]
  end
 end

 def []=(a,b,c,x)
  @store[a] = [[]] if @store[a]==nil
  @store[a][b] = [] if @store[a][b]==nil
  @store[a][b][c] = x
 end
end


array = Array3.new
array[1,2,3] = 4
puts array[1,2,3] # => 4
puts array[1,1,1] # => 0
0
edymerchk

Il peut être utile de se rappeler que le tableau est un objet dans Ruby et que les objets ne sont pas (par défaut) créés simplement en les nommant ou en nommant la référence à l'objet. Voici une routine pour créer un tableau à 3 dimensions et le vider à l'écran pour vérification:

 def Create3DimensionArray (x, y, z, valeur par défaut) 
 n = 0 # code de vérification uniquement 
 ar = Array.new (x) 
 pour i en 0 ... x 
 ar [i] = Array.new (y) 
 pour j dans 0 ... y 
 ar [i] [j] = Array.new (z, par défaut) 
 pour k dans 0 ... z # code de vérification uniquement 
 ar [i] [j] [k] = n # code de vérification uniquement 
 n + = 1 # code de vérification uniquement 
 fin # code de vérification seulement 
 fin
 fin
 return ar 
 end 

 # Crée un échantillon et vérifie
ar = Create3DimensionArray (3, 7, 10, 0) 

 pour x dans ar 
 met "||" 
 pour y dans x 
 met "|" 
 pour z dans y 
 printf "% d", z 
 fin
 fin 
 fin
0
mhdecoursey

Peut-être que vous pouvez simuler votre tableau multidimensionnel avec un hachage. La clé de hachage peut être utilisée par n'importe quel objet Ruby, vous pouvez donc aussi prendre un tableau.

Exemple:

marray = {}
p marray[[1,2]]   #-> nil
marray[[1,2]] = :a
p marray[[1,2]]   #-> :a

Sur la base de cette idée, vous pouvez définir une nouvelle classe.

Juste un scénario rapide:

=begin rdoc
Define a multidimensional array.

The keys must be Fixnum.

The following features from Array are not supported:
* negative keys (Like Array[-1])
* No methods <<, each, ...
=end
class MArray
  INFINITY = Float::INFINITY
=begin rdoc
=end
  def initialize(dimensions=2, *limits)
    @dimensions = dimensions
    raise ArgumentError if limits.size > dimensions
    @limits = []
    0.upto(@dimensions-1){|i|
      @limits << (limits[i] || INFINITY)
    }
    @content = {}
  end
  attr_reader :dimensions
  attr_reader :limits
=begin rdoc
=end
  def checkkeys(keys)
    raise ArgumentError, "Additional key values for %i-dimensional Array" % @dimensions if keys.size > @dimensions
    raise ArgumentError, "Missing key values for %i-dimensional Array" % @dimensions if keys.size != @dimensions
    raise ArgumentError, "No keys given" if keys.size == 0
    keys.each_with_index{|key,i|
      raise ArgumentError, "Exceeded limit for %i dimension" % (i+1) if key > @limits[i]
      raise ArgumentError, "Only positive numbers allowed" if key < 1

    }
  end
  def[]=(*keys)
    data = keys.pop
    checkkeys(keys)
    @content[keys] = data
  end
  def[](*keys)
    checkkeys(keys)
    @content[keys]
  end
end

Ceci peut être utilisé comme:

arr = MArray.new()
arr[1,1] = 3
arr[2,2] = 3

Si vous avez besoin d'une matrice 2x2 prédéfinie, vous pouvez l'utiliser comme:

arr = MArray.new(2,2,2)
arr[1,1] = 3
arr[2,2] = 3
#~ arr[3,2] = 3  #Exceeded limit for 1 dimension (ArgumentError)

Je pourrais imaginer comment gérer des commandes telles que << ou each dans un tableau à deux dimensions, mais pas dans des tableaux à plusieurs dimensions.

0
knut