eigene Listentypes (mit ArrayList-Beispiel)

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

mpmxyz

Betreff: eigene Listentypes (mit ArrayList-Beispiel)

BeitragFr, Dez 25, 2009 1:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielleicht hat jemand von euch schon einmal mit dem Gedanken gespielt, einen eigenen Listentype zu schreiben, und hat es aber dann aufgegeben, weil er nicht herausgefunden hat, wie man diese Listen einfach mit "EachIn" durchgehen kann.

Ich selbst habe aber im Modulcode von BlitzMax eine Lösung gefunden, wie man eigene Types iterierbar macht.
Damit eine eigene Liste mit "EachIn" durchgegegangen werden kann, muss es einen dazu Passenden Enumerator-Type geben und beide Types müssen sich an diese Vorlage halten:
BlitzMax: [AUSKLAPPEN]
Type TIterable Abstract
Method ObjectEnumerator:TEnumerator() Abstract 'erstellt in der "EachIn"-Schleife ein TEnumerator-Objekt, setzt den aktuellen Eintrag auf den ersten Eintrag und gibt das TEnumerator-Objekt zurück
EndType

Type TEnumerator Abstract
Method HasNext:Int() Abstract 'Gibt True zurück, wenn der AKTUELLE Eintrag ein Listeneintrag ist
Method NextObject:Object() Abstract 'Gibt das Objekt des AKTUELLEN Eintrags zurück und geht zum nächsten Eintrag
EndType

(Es muss nicht von den abstrakten Types, die ich selbst geschrieben habe, geerbt werden, auch wenn es ein besserer Codingstil wäre.)

Am Besten zeige ich ein Beispiel, dass selbst eigentlich einen eigenen Platz im Codearchiv verdient hätte:
BlitzMax: [AUSKLAPPEN]
SuperStrict
Framework brl.Blitz
Import brl.Math
Import brl.StandardIO



Type TEnumerator Abstract
Method HasNext:Int() Abstract
Method NextObject:Object() Abstract
EndType

Type TIterable Abstract
Method ObjectEnumerator:TEnumerator() Abstract
EndType


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Das Testprogramm:

Local List:TArrayList=TArrayList.Create()

For Local Z:Int=0 Until 10
List.Add(String(Z))
Next

For Local s:String=EachIn(List)
Print s
Next
Print
List.Add("S",2)
For Local s:String=EachIn(List)
Print s
Next
Print
List.Remove(3)
For Local s:String=EachIn(List)
Print s
Next
Print
Print String(List.Value(3))
End
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


Type TArrayList Extends TIterable
Field _Array:Object[]
Field _Count:Int=0
Field _Locked:Int=0'Die ArrayList verkleinert sich dann nicht mehr (beim häufigen Entfernen und Hinzufügen von Objekten ist die ArrayList dann schneller)

Field _ResizeFactor:Double'Wachstums-/Schrumpf-Faktor
Field _ShrinkFactor:Double'Bedingung für das Verkleinern, je kleiner er ist, desto seltener wird die ArrayList verkleinert

Method New() Private
EndMethod

Rem
Beschreibung:
erstellt eine ArrayList
Parameter:
Size: gibt die Startgröße des Arrays an
ResizeFactor: Wenn dass Array zu groß ist, wird es auf diesen Faktor vergrößert. (bei 2 wird die Größe verdoppelt)
ShrinkFactor: Dieser Faktor bestimmt die minimalen Anteil der benutzten Arrayfelder an. Wenn zu viele Felder unbenutzt sind, wird das Array verkleinert.
Rückgabewert:
Die ArrayList
EndRem

Function Create:TArrayList(Size:Int=32,ResizeFactor:Double=1.5,ShrinkFactor:Double=0.5)
If ResizeFactor<=1 Then Return Null
If ShrinkFactor>=1 Then Return Null
If ShrinkFactor*ResizeFactor>1 Then Return Null 'Beim Verkleinern würden die Arrays zu klein werden
Local ArrayList:TArrayList=New TArrayList
ArrayList._Array=New Object[Size]
ArrayList._ResizeFactor=ResizeFactor
ArrayList._ShrinkFactor=ShrinkFactor
Return ArrayList
EndFunction


Rem
Beschreibung:
Diese Methode erstellt einen Eintrag in der ArrayList
Parameter:
Value: Der Eintragswert
ID: Die Position, an der der neue Eintrag eingefügt werden soll.
Wenn er -1 ist, dann wird ein neuer Eintrag am Ende erstellt.
Rückgabewert:
Wenn der Eintrag eigefügt werden konnte, wird die ID des Eintrages zurückgegeben.
Wenn nicht, wird -1 zurückgegeben.
EndRem

Method Add:Int(Value:Object,ID:Int=-1)
If ID>Self._Count Then Return -1
If ID<-1 Then Return -1

If ID=-1
ID=Self._Count
EndIf
Self._Count:+1

If Self._Count>Self._Array.length'Das Array ist zu klein.
Self._Array=Self._Array[..Ceil(Self._Array.length*Self._ResizeFactor)] 'Array resizen
EndIf

For Local FromID:Int=Self._Count-2 To ID Step -1 'Wenn der neue Eintrag innerhalb der Liste entstehen soll, müssen die Einträge nach ihm um einen Platz nach hinten rutschen.
Self._Array[FromID+1]=Self._Array[FromID]
Next

Self._Array[ID]=Value
Return ID
EndMethod

Rem
Beschreibung:
Diese Methode entfernt einen Eintrag und lässt alle Nachfolgenden Einträge aufrücken.
Parameter:
ID: die ID des zu entfernenden Eintrages
Rückgabewert:
Gibt True zurück, ob der Eintrag entfernt werden konnte
EndRem

Method Remove:Int(ID:Int)
If ID>=Self._Count Then Return False
If ID<0 Then Return False
Self._Array[ID]=Null
For Local FromID:Int=ID+1 Until Self._Count 'Wenn der zu löschende Eintrag innerhalb der Liste steht, müssen die Einträge nach ihm um einen Platz nach vorne rutschen.
Self._Array[FromID-1]=Self._Array[FromID]
Next

Self._Count:-1
Self.ShrinkCheck() 'Testen, ob das Array verkleinert werden kann
Return True
EndMethod

Rem
Beschreibung:
Diese Methode schaut, ob das Array der ArrayList verkleinert werden kann und macht es, wenn nötig.
Rückgabewert:
Gibt True zurück, wenn das Array verkleinert wurde
EndRem

Method ShrinkCheck:Int() 'Gibt True zurück, wenn das Array verkleinert wurde
If Self._Locked=0
If Self._Count<Floor(Self._Array.length*Self._ShrinkFactor)
Self._Array=Self._Array[..Ceil(Self._Array.length/Self._ResizeFactor)] 'Array resizen
Return True
EndIf
EndIf
Return False
EndMethod

Rem
Beschreibung:
Diese Methode sperrt eine Arraylist, damit deren Array nicht mehr verkleinert wird.
Dies kann beim Häufigen Löschen und Hinzufügen einen großen Geschwindigkeitsbonus geben.
EndRem

Method Lock()
Self._Locked:+1
EndMethod

Rem
Beschreibung:
Diese Methode hebt die Sperrung von Lock() auf.
Rückgabewert:
Gibt True zurück, wenn das Array verkleinert wurde
EndRem

Method UnLock:Int()
Self._Locked:-1
If Self._Locked<0 Then Self._Locked=0
Return Self.ShrinkCheck()
EndMethod

Rem
Beschreibung:
Diese Methode gibt die Anzahl an Einträgen der ArrayList zurück.
Rückgabewert:
Die Anzahl der Einträge
EndRem

Method Count:Int()
Return Self._Count
EndMethod

Rem
Beschreibung:
Diese Methode gibt den Wert des angegebenen Eintrages zurück.
Parameter:
ID: die ID eines Eintrages
Rückgabewert:
Der Wert des Eintrages
EndRem

Method Value:Object(ID:Int)
If ID>=Self._Count Then Return Null
If ID<0 Then Return Null
Return Self._Array[ID]
EndMethod

Rem
Beschreibung:
Diese Methode ist dazu da, dass ein ArrayList-Objekt in einer "EachIn"-Schleife genutzt werden kann.
Rückgabewert:
Das Enumerator-Objekt, dass von der "EachIn"-Schleife genutzt wird.
EndRem

Method ObjectEnumerator:TArrayListEnum()
Return TArrayListEnum.Create(Self)
EndMethod
EndType

Rem
Beschreibung:
Dieser Type ist dazu da, dass ein ArrayList-Objekt in einer "EachIn"-Schleife genutzt werden kann.
EndRem

Type TArrayListEnum Extends TEnumerator
Field _ArrayList:TArrayList
Field _ID:Int=0
Function Create:TArrayListEnum(ArrayList:TArrayList)
Local Enum:TArrayListEnum=New TArrayListEnum
Enum._ArrayList=ArrayList
Return Enum
End Function

Method HasNext:Int()
If Self._ID<_ArrayList._Count Then Return True
Return False
End Method

Method NextObject:Object()
Local value:Object=_ArrayList._Array[Self._ID]
Self._ID:+1
Return value
End Method
EndType


So...
Jetzt bin ich auf eure Kommentare gespannt.

mfG
mpmxyz

Edit: Ja, ich habe den BlitzMax-Hilfeeintrag überlesen; die Hilfe könnte meiner Meinung nach aber auch ein bischen übersichtlicher sein...
  • Zuletzt bearbeitet von mpmxyz am Fr, Dez 25, 2009 12:46, insgesamt einmal bearbeitet

Noobody

BeitragFr, Dez 25, 2009 10:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Das wird übrigens in der BlitzMax - Hilfe unter "Language Reference -> Collections" erklärt Wink
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

mpmxyz

BeitragFr, Dez 25, 2009 12:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh, da war ich wohl etwas müde gewesen...
Naja, dann überlest mal diesen inhaltlichen Fehler und kommentiert nur noch die ArrayList. Razz
Weitere Funktionen werde ich da wahrscheinlich noch hinzufügen.

mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group