Подтвердить что ты не робот

Многомерный массив Ruby

Возможно, это просто моя нехватка способностей найти здесь эту проблему, но я не могу найти ничего о том, как создавать многомерные массивы в Ruby.

Может кто-нибудь, пожалуйста, дайте мне пример о том, как это сделать?

4b9b3361

Ответ 1

Строго говоря, в Ruby невозможно создать многомерные массивы. Но можно поместить массив в другой массив, который почти такой же, как многомерный массив.

Вот как вы могли бы создать 2D-массив в Ruby:

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

<ч/" > Как указано в комментариях, вы также можете использовать NArray, который представляет собой библиотеку числовых массивов Ruby:

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

Используйте a[i][j] для доступа к элементам массива. В основном a[i] возвращает "вспомогательный массив", сохраненный в позиции i из a, и, таким образом, a[i][j] возвращает номер элемента j из массива, который хранится в позиции i.

Ответ 2

вы можете передать блок Array.new

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

значение, возвращающее блок, будет значением каждого индекса первого массива,

поэтому..

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

и вы можете получить доступ к этому массиву с помощью array[x][y]

также для второго экземпляра массива, вы также можете передать блок как значение по умолчанию. так

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

Ответ 3

Просто уточнение:

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

совсем не совпадает с:

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

в последнем случае попробуйте:

arr[0][0] = 99

и вот что вы получили:

[[99,5], [99,5]]

Ответ 4

Есть два способа инициализации мульти-массива (размер 2). Все остальные ответы показывают примеры со значением по умолчанию.

Объявите каждый из подмассива (вы можете сделать это во время выполнения):

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

или объявите размер родительского массива при инициализации:

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

Пример использования:

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"

Таким образом, вы можете обернуть первый способ и использовать его так:

@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"

Ответ 5

Указанный выше метод не работает.

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

эквивалентно

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]

и будет печатать 1.0, а не 0.0, потому что мы являемся modifiyng array a и печатаем элемент массива a.

Ответ 6

На самом деле это намного быстрее, чем метод блока, приведенный выше:

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

arr[0][1][2] += 1

Ответ 7

Мне недавно пришлось воспроизвести многомерный массив PHP-стиля в Ruby. Вот что я сделал:

# 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

Ответ 8

Возможно, вы можете смоделировать свой многомерный массив с помощью Hash. Хэш-ключ может быть любым объектом Ruby, поэтому вы также можете взять массив.

Пример:

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

На основе этой идеи вы можете определить новый класс.

Просто быстрый сценарий:

=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

Это можно использовать как:

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

Если вам нужна предопределенная матрица 2x2, вы можете использовать ее как:

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

Я мог представить, как обрабатывать команды типа << или each в двумерном массиве, но не в многомерных.

Ответ 9

Это может помочь вспомнить, что массив является объектом в ruby, а объекты (по умолчанию) создаются просто путем их именования или назначения ссылки на объект. Вот процедура создания 3-мерного массива и сброс его на экран для проверки:

def Create3DimensionArray(x, y, z, default)
    n = 0                       # verification code only
    ar = Array.new(x)
    for i in 0...x
        ar[i] = Array.new(y)
        for j in 0...y
            ar[i][j] = Array.new(z, default)
            for k in 0...z      # verification code only
                ar[i][j][k] = n # verification code only
                n += 1          # verification code only
            end                 # verification code only
        end
    end
    return ar
end

# Create sample and verify
ar = Create3DimensionArray(3, 7, 10, 0)

for x in ar
    puts "||"
    for y in x
        puts "|"
        for z in y
            printf "%d ", z
        end
    end
end

Ответ 10

Вот реализация класса 3D-массива в ruby, в этом случае значение по умолчанию равно 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

Ответ 11

Использование может также использовать XKeys Gem.

require 'xkeys'

regular = [].extend XKeys::Auto
regular[1,2,3] = 4
# [nil, [nil, nil, [nil, nil, nil, 4]]]
regular[3,2,1, :else=>0] # 0
# Note: regular[1,2] is a slice
# Use regular[1,2,{}] to access regular[1][2]

sparse = {}.extend XKeys::Hash
sparse[1,2,3] = 4
# {1=>{2=>{3=>4}}}
path=[1,2,3]
sparse[*path,{}] # 4