Ich frage mich, ob es eine Möglichkeit gibt, ein zweidimensionales Array zu erstellen und schnell auf ein horizontales oder vertikales Sub-Array darin zuzugreifen.
Ich glaube, wir können im folgenden Fall auf ein horizontales Subarray zugreifen:
x = Array.new(10) { Array.new(20) }
x[6][3..8] = 'something'
Aber soweit ich weiß, können wir nicht so darauf zugreifen:
x[3..8][6]
Wie kann ich dieses Limit vermeiden oder hacken?
x[3..8].each{|a|a[6] = 'something'}
ist zu hässlich für dich.Antworten:
Es gibt einige Probleme mit der zweidimensionalen
Arrays
Implementierung.a= [[1,2],[3,4]] a[0][2]= 5 # works a[2][0]= 6 # error
Hash
wieArray
Ich bevorzuge es
Hashes
für mehrdimensionaleArrays
a= Hash.new a[[1,2]]= 23 a[[5,6]]= 42
Dies hat den Vorteil, dass Sie keine Spalten oder Zeilen manuell erstellen müssen. Das Einfügen in Hashes ist fast O (1) , daher gibt es hier keinen Nachteil, solange Ihr
Hash
nicht zu groß wird.Sie können sogar einen Standardwert für alle nicht angegebenen Elemente festlegen
a= Hash.new(0)
Nun also darüber, wie man Subarrays bekommt
(3..5).to_a.product([2]).collect { |index| a[index] } [2].product((3..5).to_a).collect { |index| a[index] }
(a..b).to_a
läuft in O (n). Das Abrufen eines Elements von aHash
ist fast O (1), daher läuft die Sammlung in fast O (n). Es gibt keine Möglichkeit, es schneller als O (n) zu machen, da das Kopieren von n Elementen immer O (n) ist.Hashes
kann Probleme haben, wenn sie zu groß werden. Ich würde also zweimal darüber nachdenken, eine solche Multidimensionale zu implementierenArray
, wenn ich wüsste, dass meine Datenmenge immer größer wird.quelle
a[2][0]
ein Fehler, weil das 3. Element noch nicht erstellt wurde? Bedeutunga[1][0]=6
würde funktionieren? Ich weiß, das ist alt ... ich schaue gerade Ruby an.a[1][0] = 6
funktioniert. Sie können die dritte Zeile mit einem [2] erstellen, aber Sie können erst nach dem Erstellen einen Index erstellen. ZBa[2] = []
gefolgt vona[2][0] = 6
wird funktionieren.almost O(1)
[...]?rows, cols = x,y # your values grid = Array.new(rows) { Array.new(cols) }
Was den Zugriff auf Elemente betrifft, ist dieser Artikel ziemlich gut geeignet, um ein Array Schritt für Schritt wie folgt zu kapseln:
Wie man Array rubin
quelle
Sie haben Ihr eigentliches Ziel nicht angegeben, aber vielleicht kann dies helfen:
require 'matrix' # bundled with Ruby m = Matrix[ [1, 2, 3], [4, 5, 6] ] m.column(0) # ==> Vector[1, 4]
(und Vektoren wirken wie Arrays)
oder mit einer ähnlichen Notation, wie Sie es wünschen:
m.minor(0..1, 2..2) # => Matrix[[3], [6]]
quelle
x[6][3..8]
Notation bevorzugen , können Sie sie jederzeit unterordnenMatrix
und erweitern.Matrix
Nachdem ich diese Antwort gelesen hatte, fing ich an zu verwenden , und es war großartig. Es gibt jedoch eine große Einschränkung, die Sie besser berücksichtigen sollten, bevorMatrix
Sie zu wechseln - sie sind unveränderlich. Es gibt also keine Möglichkeit, ein einzelnes Element zu ändern, dhm(0, 0) = 0 # => error
Matrix
. Ihre Unveränderlichkeit würde ich nicht als Einschränkung, sondern als Merkmal bezeichnen. Anscheinend macht Marc-Anré sich nicht nur das Leben leichter, sondern präsentiert Matrizen auch als Verallgemeinerung von Zahlen.OpenMatrix
zum Beispiel, wieOpenStruct
undStruct
), oder der Benutzer hat zunächst so etwas wie zu tun ,Matrix#open
oder ,#unlock
oder was.Hier ist ein 3D-Array-Fall
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
Sie können wie jedes andere Ruby-Array auf Unterabschnitte jedes Arrays zugreifen. @data [0..2] [3..5] [8..10] = 0 usw.
quelle
x.transpose[6][3..8]
oderx[3..8].map {|r| r [6]}
würde geben was du willst.Beispiel:
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]
quelle
transpose
? Großartig!collect
stattmap
fügt hier ein wenig Klarheit hinzu.Ich bin mir ziemlich sicher, dass dies sehr einfach sein kann
2.0.0p247 :032 > list = Array.new(5) => [nil, nil, nil, nil, nil] 2.0.0p247 :033 > list.map!{ |x| x = [0] } => [[0], [0], [0], [0], [0]] 2.0.0p247 :034 > list[0][0] => 0
quelle
x
wie[0]
sowieso zurückgegeben wirdArray.new
kann einen Block direkt nehmen, keine Notwendigkeit fürmap
:Array.new(5) {|x| x = [0] }
=> [[0], [0], [0], [0], [0]]
oder noch einfacher:Array.new(5,[0])
=> [[0], [0], [0], [0], [0]]
a = Array.new(Array.new(4)) 0.upto(a.length-1) do |i| 0.upto(a.length-1) do |j| a[i[j]] = 1 end end 0.upto(a.length-1) do |i| 0.upto(a.length-1) do |j| print a[i[j]] = 1 #It's not a[i][j], but a[i[j]] end puts "\n" end
quelle
Hier ist die einfache Version
#one a = [[0]*10]*10 #two row, col = 10, 10 a = [[0]*row]*col
quelle
Hier ist eine einfache Möglichkeit, ein "2D" -Array zu erstellen.
2.1.1 :004 > m=Array.new(3,Array.new(3,true)) => [[true, true, true], [true, true, true], [true, true, true]]
quelle
m=Array.new(3){Array.new(3, true)}
. Das würde Ihnen 4 Arrays und 3 Boolesche Objekte geben.