Seite 1 von 2
kleine Erweiterung für Maps
Verfasst: 14.03.2011 01:30
von STARGÅTE
Tachchen,
immer wieder stolper ich darüber, dass wenn ich mit Pointern zu MapElementen arbeiten, später nicht mehr weiß wie ich an den Key zu diesem Pointer komme...
Nach ein bisschen probieren, bin ich auf folgendes Macro gekommen:
Code: Alles auswählen
Macro MapElementKey(Pointer)
PeekS(PeekI(Pointer-SizeOf(Integer)))
EndMacro
Zusätzlichen kann man dann auch eine "Art" ChangeCurrentMapElement() machen:
Code: Alles auswählen
Macro MapElementKey(Pointer)
PeekS(PeekI(Pointer-SizeOf(Integer)))
EndMacro
Macro ChangeCurrentMapElement(Map, Pointer)
FindMapElement(Map, MapElementKey(Pointer))
EndMacro
;-----
NewMap Test.i()
Test("Alpha") = 1
Test("Beta") = 2
Test("Gamma") = 3
*Pointer = @Test("Beta")
Debug MapElementKey(*Pointer)
Debug ""
ForEach Test()
Debug MapKey(Test())
*Save = @Test()
ForEach Test()
Debug " "+MapKey(Test())
Next
ChangeCurrentMapElement(Test(), *Save)
Next
Ich hoffe das die Adresse zum Key auch an dieser Stelle bleibt ^^
Re: kleine Erweiterung für Maps
Verfasst: 14.03.2011 14:27
von CSHW89
Hey danke,
genau wegen diesem Fehlen, hab ich z.Z. immer die Maps gemieden. Die doppelte ForEach-Schleife, wie in deinem Beispiel, konnte man nämlich vorher nicht machen.
Also danke, dass du mir die Tür zu den Maps geöffnet hast
lg kevin
Re: kleine Erweiterung für Maps
Verfasst: 14.03.2011 18:14
von STARGÅTE
Doppelte ForEach-Schleife ging schon, nur muss mal halt statt einem Pointer (wie bei LL) den Key-Namen Speichern und dann über FindMapElement wieder "in die Schleife" springen.
Das mache ich ja immer noch, nur halt versteckt über das Macro mittels Pointer, der erst den Namen ermittelt.
Re: kleine Erweiterung für Maps
Verfasst: 14.03.2011 23:23
von CSHW89
Ja ging schon, nur war das nicht sooo schnell, da durch FindMapElement erst das Element gesucht werden musste (Zeit: O(log n), mit deiner Methode: O(1), falls du die Notation kennst

).
Außerdem musste man dadurch erstmal den Key haben, was bei meinen Programmen manchmal nicht ging bzw. viel komplizierter war.
lg kevin
Re: kleine Erweiterung für Maps
Verfasst: 14.03.2011 23:30
von NicTheQuick
Stargate wollte dir damit sagen, dass es bei seiner obigen Methode immer noch O(log(n)) ist, weil 'FindMapElement()' immer noch verwendet wird.
Re: kleine Erweiterung für Maps
Verfasst: 14.03.2011 23:36
von CSHW89
Oh stimmt, sorry

. Habs falsch gelesen. Ich dachte Stargate hätte ChangeCurrentMapElement auch "zu Fuß" geschrieben. Also den Pointer des aktuellen Elements geändert.
lg kevin
Re: kleine Erweiterung für Maps
Verfasst: 14.03.2011 23:40
von STARGÅTE
Oke, ich probier mal, ob ich über den Pointer zum Header der Map (ist glaube ich an Position -12)
Das Aktuelle Element überschreiben kann ...
melde mich dann wieder
Re: kleine Erweiterung für Maps
Verfasst: 15.03.2011 12:33
von STARGÅTE
Tia, also ich kann leider nichts weiter finden:
Code: Alles auswählen
Macro MapHeader(Pointer)
PeekI(Pointer-SizeOf(Integer)*3)
EndMacro
NewMap Test.i()
Test("Alpha") = 11
Test("Beta") = 22
Test("Gamma") = 33
*CurrentElement = @Test("Beta")
*MapHeader = MapHeader(*CurrentElement)
Debug *CurrentElement
Debug "MapSize : "+Str(PeekI(*MapHeader+16))
For Pos = -80 To 80 Step 4
*Pointer = *MapHeader+Pos
Debug RSet(Str(Pos),4)+": "+RSet(Hex(PeekL(*Pointer),#PB_Long),8,"0")+" "+RSet(Str(PeekL(*Pointer)),11)+" "+PeekS(*Pointer)
Next
Was ich erkenne ist, das bei HeaderPosition+16 die Map-Größe gespeichert wird.
Darüber hinaus, kommen ab +24 alle Elemente der Map mit Header und Inhalt ...
Auch vor dem HeaderPosition steht nichts zum aktuellen Element, dort finde ich bei -44 nur die Größe eines MapElement (Header+Structure), denn wenn ich eine Map aus Quads erstelle, wird aus der 16 n 20.
Aber leider kann ich halt nirgends den Pointer des aktuellen Element wieder finden, nicht mal 12Byte kleiner, weil zB nicht der Pointer zum Inhalt gespeichert wird, sondern zum Header des Elements
Re: kleine Erweiterung für Maps
Verfasst: 15.03.2011 15:20
von CSHW89
Ich habs! Ich kenn das nämlich noch von den Listen. Da musste ich mir auch ansehen, wie sie gespeichert werden (für PBScript).
Es gibt zwei Speicherstellen, warum auch immer. Einmal den Header, den du raussuchst, und noch ein weiterer, der z.b. übergeben wird, wenn im Parameter 'Map' steht. Hier mal ein dirty-workaround, um den Wert zu bekommen (der erste Wert):
Code: Alles auswählen
Macro MapHeader(Pointer)
PeekI(Pointer-SizeOf(Integer)*3)
EndMacro
Procedure HeaderValue(header.i)
ProcedureReturn header
EndProcedure
Prototype HeaderValueMap(Map test.i())
HeaderValueMap.HeaderValueMap = @HeaderValue()
NewMap test.i()
test("Hallo") = 1
test("Test") = 2
Debug HeaderValueMap(test())
Debug MapHeader(@test())
An dieser Speicherposition ist direkt das aktuelle Element gespeichert. Frag mich aber nicht, wie man ihn sonst herbekommt, also für alle Arten von Maps. Da hab ich grad keine Ahnung. Werd nochmal drüber grübeln.
lg kevin
Re: kleine Erweiterung für Maps
Verfasst: 04.04.2011 01:25
von STARGÅTE
Seit Beta 4.60 wurde zumindest das "merken" von elementen einfacher:
Danke PushMapPosition() und PopMapPosition() kann man nun leichter zum "alten" Element springen, und da sogar in mehreren Leveln:
Code: Alles auswählen
NewMap Test.i()
Test("Alpha") = 1
Test("Beta") = 2
Test("Gamma") = 3
ForEach Test()
Debug MapKey(Test())
PushMapPosition(Test())
ForEach Test()
Debug " "+MapKey(Test())
PushMapPosition(Test())
ForEach Test()
Debug " "+MapKey(Test())
Next
PopMapPosition(Test())
Next
PopMapPosition(Test())
Next