Größenveränderbares 1- und 2-dimensionales Array

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

 

Shaman

Betreff: Größenveränderbares 1- und 2-dimensionales Array

BeitragDi, Okt 11, 2011 20:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich stelle hier zwei Klassen vor, die 1-, bzw. 2-dimensionale Arrays darstellen.
TArray1D und TArray2D.

Diese Arrays sind
größenveränderbar,
erlauben negative Indizes (Offset Rechnung) und
kann man in einer for each - Schleife durchlaufen.
außerdem vollständig dokumentiert

Erstmal der Code:
1-dimensionale Version:
Code: [AUSKLAPPEN]

Rem
bbdoc: Interface for Enumerators
EndRem
Type TEnumerator Abstract
   Method HasNext:Int() Abstract
   Method NextObject:Object() Abstract
EndType

Rem
bbdoc: Interface for iterable Objects
EndRem
Type TIterable Abstract
   Method ObjectEnumerator:TEnumerator() Abstract
EndType

Rem
bbdoc: A one-dimensional array of Objects
EndRem
Type TArray1D Extends TIterable
   Field _array:Object[]
   Field _size:Int
   Field _off:Int
   
   Method New() Private
   EndMethod
   
   Rem
   bbdoc: Creates the one-dimensional  Array
   returns: the array
   about: size is the startsize and <br>
   offset is the start offset (for negative indexes)
   EndRem
   Function Create:TArray1D(size:Int=32,offset:Int=0)
      Local a:TArray1D=New TArray1D
      a._array=a._array[..size]
      a._size=Size
      a._off=Offset
      Return a
   EndFunction
   
   Rem
   bbdoc: Sets a value
   about: if the index is out of range, 0 is returned, else 1
   EndRem
   Method Set:Byte(x:Int,obj:Object)
      x:+_off
      If x<0 Or x>=_size Then Return 0
      _array[x]=obj
      Return 1
   End Method
   
   Rem
   bbdoc: Gets a value
   returns: if the index is out of range, null is returned, else the value
   EndRem
   Method Get:Object(x:Int)
      x:+_off
      If x<0 Or x>=_size Then Return Null
      Return _array[x]
   End Method
   
   Rem
   bbdoc: Resizes the array
   about: size is the new size, and offset the new offset <br>
   Example: <br>
   an array with size=10 and offset=-3: <br>
   min. index is at x=-3 , max. index is at x=6
   EndRem
   Method Resize(size:Int,offset:Int)
      Local a:Object[]
      Local i:Int
      Local diff:Int
      If offset<>_off Or size<>_size Then
         'Resize in x-Richtung
         diff=-(offset+_off)
         If diff<0 Then Throw("Array2D can only become bigger")
         If size<_size Then Throw("Array2D can only become bigger")
         a=a[..size]
         
         For i=0 Until _size
            a[i+diff]=_array[i]
         Next
         _array=a
         _off=offset
         _size=size
      EndIf
   End Method
   
   Rem
      bbdoc: Diese Methode ist dazu da, dass ein Array1D-Objekt in einer "EachIn"-Schleife genutzt werden kann.
      returns:
         Das Enumerator-Objekt, dass von der "EachIn"-Schleife genutzt wird.
   EndRem
   Method ObjectEnumerator:TArray1DEnum()
      Return TArray1DEnum.Create(Self)
   EndMethod
End Type
      
            
Rem
bbdoc: Enumerator for TArray2D
EndRem
Type TArray1DEnum Extends TEnumerator
   Field _array1D:TArray1D
   Field _x:Int
   Function Create:TArray1DEnum(array1D:TArray1D)
      Local enum:TArray1DEnum=New TArray1DEnum
      enum._x=0
      enum._array1D=array1D
      Return enum
   End Function
   
   Method HasNext:Int()
      If Self._x<_array1D._size Then Return True
      Return False
   End Method
   
   Method NextObject:Object()
      Local value:Object=_array1D._array[Self._x]
      Self._x:+1
      Return value
   End Method
End Type


Und die 2-dimensionale Version:
Code: [AUSKLAPPEN]

Rem
bbdoc: A two-dimensional array of Objects
EndRem
Type TArray2D Extends TIterable
   Field _array:TArray1D[]
   Field _size:Int
   Field _off:Int
   
   Method New() Private
   EndMethod
   
   Rem
   bbdoc: Creates the two-dimensional Array
   returns: the array
   about: size is the startsize and <br>
   offset is the start offset (for negative indexes) <br>
   in both directions each
   EndRem
   Function Create:TArray2D(sizeX:Int=32,sizeY:Int=32,offsetX:Int=0,offsetY:Int=0)
      Local a:TArray2D=New TArray2D
      a._array=a._array[..SizeX]
      a._size=sizeX
      a._off=offsetX
      Local i:Int
      For i=0 Until sizeX
         a._array[i]=TArray1D.Create(sizeY,offsetY)
      Next
      Return a
   EndFunction
   
   Rem
   bbdoc: Sets a value
   about: if the index is out of range, 0 is returned, else 1
   EndRem
   Method Set:Byte(x:Int,y:Int,obj:Object)
      x:+_off
      If x<0 Or x>=_size Then Return 0
      Return _array[x].Set(y,obj)
      Return 1
   End Method
   
   Rem
   bbdoc: Gets a value
   returns: if the index is out of range, null is returned, else the value
   EndRem
   Method Get:Object(x:Int,y:Int)
      x:+_off
      If x<0 Or x>=_size Then Return Null
      Return _array[x].Get(y)
   End Method
   
   Rem
   bbdoc: Resizes the array
   about: size is the new size, and offset the new offset <br>
   in both directions each. <br>
   see #Resize
   EndRem
   Method Resize(sizeX:Int,sizeY:Int,offsetX:Int,offsetY:Int)
      Local a:TArray1D[]
      Local i:Int
      Local diff:Int
      
      'Resize in x-Richtung
      diff=-(offsetX+_off)
      If diff<0 Then Throw("Array2D can only become bigger")
      If sizeX<_size Then Throw("Array2D can only become bigger")
      a=a[..sizeX]
      
      For i=0 Until _size
         _array[i].Resize(sizeY,offsetY)
         a[i+diff]=_array[i]
      Next
      _array=a
      _off=offsetX
      _size=sizeX
      
   End Method
   
   Rem
      bbdoc: Diese Methode ist dazu da, dass ein Array2D-Objekt in einer "EachIn"-Schleife genutzt werden kann.
      returns:
         Das Enumerator-Objekt, dass von der "EachIn"-Schleife genutzt wird.
   EndRem
   Method ObjectEnumerator:TArray2DEnum()
      Return TArray2DEnum.Create(Self)
   EndMethod
End Type

Rem
bbdoc: Enumerator for TArray2D
EndRem
Type TArray2DEnum Extends TEnumerator
   Field _array2D:TArray2D
   Field _x:Int
   Field _a1DEnum:TArray1DEnum
   Function Create:TArray2DEnum(array2D:TArray2D)
      Local enum:TArray2DEnum=New TArray2DEnum
      enum._x=0
      enum._array2D=array2D
      enum._a1DEnum=array2D._array[0].ObjectEnumerator()
      Return enum
   End Function
   
   Method HasNext:Int()
      If Self._x<_array2D._size-1 Then Return True
      If Self._x<_array2D._size Then
         If Self._a1DEnum Then
            Return Self._a1DEnum.HasNext()
         Else
            Return False
         EndIf
      EndIf
      Return False
   End Method
   
   Method NextObject:Object()
      If Self._a1DEnum.HasNext()=True Then
         Return Self._a1DEnum.NextObject()
      Else
         Self._x:+1
         Self._a1DEnum = _array2D._array[Self._x].ObjectEnumerator()
         Return _a1DEnum.NextObject()
      EndIf
   End Method
End Type



Zur Verwendung:
Code: [AUSKLAPPEN]

Local a:TArray2D=TArray2D.Create(5,8,2,3) ' Erstellt ein zwei-dim. Array mit x-Breite 5 und y-Höhe 8. Es fängt bei -2 bzw. -3 an

a.Set(-2,-3,"kleinster index")
a.Set(2,4,"größter index")

a.Set(0,0,"test")
Print String(a.Get(0,0)) ' --> "test"

a.Resize(10,11,2,3) ' 5 spalten und 3 zeilen ans Ende angehängt, offset bleibt gleich.
a.Set(7,7,"größter index")

'Iterator - Test (2-dimensional als Beispiel)
local b:TArray2D=TArray2D.Create(5,5,0,0)
local x:int,y:int
For x=0 to 4
  For y=0 to 4
     b.Set(x,y,String(x+","+y))
  Next
Next

'Iteration:
Local str:String
For str = eachin b
  Print str
Next
 


Bei Fragen bitte melden.

P.S. Code zum verkleinern des Arrays ist noch nicht vollständig, wenn jemand ihn schreibt freuts mich

Thunder

BeitragMi, Okt 12, 2011 21:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Verstehe ich nicht ganz. Normale Arrays sind doch auch in der Größe veränderbar können mit einer for-eachin Schleife durchlaufen werden, nicht?

BlitzMax: [AUSKLAPPEN]
' aus der BlitzMax-Hilfe:
Local a[200] 'initialize a[] to 200 elements
a=a[50..150] 'extract middle 100 elements of a[]
a=a[..50] 'extract first 50 elements of a[]
a=a[25..] 'extract elements starting from index 25 of a[]
a=a[..] 'copy all elements of a[]
a=a[..200] 'resize a[] to 200 elements

'selbst geschrieben:

a=[20,40,60,42,3141592]

For x:Int=EachIn a
Print x
Next


Ich meine, negative Indizes sind sicher auch ein gutes Feature, aber dafür ein Modul einbinden ist auch etwas unnötig. Kann man eventuell die Standardmodule so verändern, dass das funktionieren würde? Das fände ich sinnvoller.

mfg Thunder
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

Der Eisvogel

BeitragMi, Okt 12, 2011 22:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Und was machst du bei Zweidimensionalen Arrays? Das geht mit BM nicht von Haus aus. Wink
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.
 

dont_know_to_use

BeitragMi, Okt 12, 2011 23:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Seit Wann sind denn Arrays größenveränderbar Thunder? BlitzBasic und -Max beherrschen keine dynamnischen Arrays. Wink

Holzchopf

Meisterpacker

BeitragMi, Okt 12, 2011 23:31
Antworten mit Zitat
Benutzer-Profile anzeigen
dont_know_to_use: BMax beherrscht Slices, was im Prinzip Nichts anderes ist Wink
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm
 

Shaman

BeitragDo, Okt 13, 2011 12:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Das besondere ist ja, dass es 2-dimensional ist.
Es kann auch leicht auf 3-dimensional und so weiter erweitert werden.

Thunder

BeitragDo, Okt 13, 2011 22:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, die Sache mit der zweidimensionalen Version konnte ich nicht widerlegen. Ich dachte das funktioniert mit Array of Array, aber das scheint bei mir nicht zu klappen, Verzeihung.
Dennoch ist es ein bisschen ... inkonsistent... wenn ich für jede Dimension einen eigenen Arraytypen brauche. Abgesehen davon, dass ich überhaupt einen Arraytypen brauche und nicht ein Array, wie es der Compiler bereitstellt, habe. Und genau darauf habe ich mich bezogen, vorher, weil ich denke, dass der BlitzMax-Compiler vielleicht einem Programmierer etwas Spielraum lässt in TEnumerator o.Ä. rumzuspielen, aber ich war/bin mir da nicht sicher.

und dont_know_to_use, auch wenn Holzchopf schon geantwortet hat: Ich habe nicht nur gesagt, das BlitzMax das (in der eindimensionalen Fassung) kann, sondern auch Code gepostet. Ich habe bis dato gedacht, meine Antwort sei idiotensicher. Im Endeffekt hat sich eh herausgestellt, dass eine Vermutung falsch war (siehe Anfang dieses Posts), aber der Code war richtig und er hat demonstriert wie ein eindimensionales Array in der Größe verändert und mit for-eachin durchlaufen wird.
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit
 

n-Halbleiter

BeitragFr, Okt 14, 2011 12:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Öhm, man kann auch Arrays of Arrays in ihrer Größe verändern, man muss nur immer in einer For-Schleife alle Elemente eines Arrays durchgehen. Ist zwar etwas unhandlich (unhandlicher als dein Code, Shaman, das wohl), allerdings dürfte es performanter sein, da einige Objekte mehr für deine Types benötigt werden. Und, was - denke ich - auch noch gegen deine Types spricht: Sie sind nicht auf einen Typ spezialisiert (was man jetzt sowohl als Vor-, als auch als Nachteil sehen kann), was bedeutet, dass man immer Casten muss; ist bei regulären Arrays nicht zwangsläufig der Fall. Und sie beherrschen keine Primitives, man müsste also, wenn man Integer speichern will, sie als String speichern und dann wieder zu Int (-> langsam)..

BlitzMax: [AUSKLAPPEN]
SuperStrict

Local rg:Int[][][]

rg=rg[..5]'Erste Dimension auf Größe 5 setzen
For Local i:Int=0 Until rg.length
rg[i]=rg[i][..5]'Zweite Dimension auf Größe 5 setzen
For Local ii:Int=0 Until rg[i].length
rg[i][ii]=rg[i][ii][..5]'Dritte Dimension auf Größe 5 setzen
Next
Next

DebugStop
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)
 

Shaman

BeitragFr, Okt 14, 2011 18:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Zu dem Problem, dass man immer casten muss:
Blitzmax beherrscht leider keine templates.
(Oder irre ich mich da?)
 

n-Halbleiter

BeitragFr, Okt 14, 2011 18:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast schon recht, BMax beherrscht keine Templates. Und genau aus diesem und den anderen o.g. Gründen denke ich, dass dein Code nicht sonderlich sinnvoll ist; das Einzige, das er bringt, ist eine Verschleierung der Arrays und damit eine Vereinfachung der nutzenden Codes.

Das sind meine zwei Cents, wenn du anderer Meinung bist, ich bin ganz Ohr. Wink
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)
 

Shaman

BeitragMo, Okt 17, 2011 4:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast recht.
Ich hab den Code auch nur zur vereinfachung geschrieben.
und aus faulheit, den Code yur groessenveraenderung immer wieder neu zu schreiben.

Firstdeathmaker

BeitragMi, Nov 02, 2011 10:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Schnell ist das aber nicht...
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image
 

Shaman

BeitragDo, Nov 03, 2011 1:12
Antworten mit Zitat
Benutzer-Profile anzeigen
inwiefern nicht schnell?

Firstdeathmaker

BeitragDo, Nov 03, 2011 9:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Im Sinne von Rechenleistung / Ergebnis. Durch solchen Overhead für einfachste Aufgaben verschwendet man viel mehr Leistung als wenn man sich einfach kurz hinsetzt und den Arrayzugriff selbst berechnet. Gerade Arrays benutze ich vor allem dann, wenn es sehr zeitkritisch ist.
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group