In diesem Fall: Das Set oder die Menge. Eine Liste von Daten, in der jedes Element nur einmal vorkommen darf. Der Versuch identische Elemente hinzuzufügen schlägt fehl.
Ein Set kann viele Funtionen haben, ich habe mich hier auf 3 beschränkt. Einfügen, Entfernen und Überprüfen ob ein Element im Set enthalten ist.
Das ganze ist OOP-mäßig aufgebaut.
Vielleicht kann es jemand gebrauchen
Code: Alles auswählen
;--- USAGE:
;-
;-? CREATE ?
; New_Set() creates a new Set by the name of [1st parameter] containing elements of the given structure [2nd parameter]
; [1st param] is now an "object" with its own methods (Add(), Delete(), Contains())
NEW_SET(X, point)
;-? ADD ?
; Time to create some variables that we want to add to the set.
Define bla.point ; Define a variable with the structure that we used to initiate our set
bla\x =1
bla\y =2
Debug "Add 1/2: " + X\add(bla) ; Use the name of the set followed by "\add( var )" to add the variable "var" to the set.
bla\x =5
bla\y =6
Debug "Add: 5/6: " + X\add(bla) ; Add another variable
bla\x =1
bla\y =2
Debug "Add: 1/2: " + X\add(bla) ; Try adding a variable already contained in the set -> False
;-? CONTAINS ?
Define blub.point ; Let's create a variable and see if "it" (an identical element) is already contained in the set.
blub\x = 1
blub\y = 2
Debug "Does Set X contain [1/2]: " + X\contains(blub) ; \contains() returns #True (1) if found or #False (0) otherwise
Debug "Delete [1/2] from set"
X\delete(blub)
Debug "Does Set X contain [1/2]: " + X\contains(blub) ; \contains() returns #True (1) if found or #False (0) otherwise
Debug "Re-ad [1/2] to the set: " + X\add(bla)
;-? CUSTOM FILTER ?
; This allows you to define a custom "filter" function to specify when exactly an item should be added. The default filter would prevent identical entries
; With a custom filter you could, as an example, specify that only POINT elements that are farther than N pixels away from 0.0 are added.
; Or "twins" of sorts. For example a ".point 3,1" must not be added when 1,3 or 3,1 are already in the set? A custom filter lets you achieve this.
; The filter shown here is no filter at all. It just shows you quickly how to define a custom filter and how to access the elements already in the set
; (To prevent double entries and such)
;
; The name of the parameters is arbitrary, as per normal procedure definition.
; The Structure of the first parameter is the structure of your elements in your set (as defined in New_Set()).
; The Structure of the second parameter is the actual name of your set (in this case "X").
; Unfortunately this means you can't use the same filter function for two sets (even though they might be virtually identical).
; This is a restriction laid upon us by the lack of OOP functionality. At least I wasn't able to find a work-around so far.
Procedure myFilter(*any.point, *bla.X)
Debug *bla\elements()\y
EndProcedure
; Lastly, you can "activate" this custom filter by using the Set_Filter() command. The first parameter is again the name of your set.
; The second parameter the name of your filter function. I added the @ that is needed in the macro Set_Filter.
; If you're used to working with Callbacks and like the call using the @ more, simply edit the Macro to your needs ;-)
; Or you could just ignore the macro that I just added for esthetic reasons and use "X\FILTER = @myFilter()" where X is of course the name of your set again.
Set_Filter(X, myFilter())
X\FILTER = @myFilter() ;use either line (not both ;-))
Include:
Code: Alles auswählen
;---BEGIN INCLUDE
EnableExplicit
Structure STRUC ;Dummy Structure needed for the prototypes. Could use point or whatever, but this way it's clear that it's a dummy.
DUMMY.i
EndStructure
; Prototypes of the functions/methods the abstract data type "SET" should have.
Prototype Proto_Set_Add(*var.STRUC)
Prototype Proto_Set_Delete(*var.STRUC)
Prototype Proto_Set_Contains(*var.STRUC)
Prototype Proto_Set_FILTER(*var.STRUC, set)
Macro Set_Filter(SET, FILTERFUNCTION) ; Just a macro for esthetic reasons. See "> ?CUSTOM FILTER ?" in the USAGE section
SET\FILTER = @FILTERFUNCTION
EndMacro
Macro New_Set(NAME, STRUCT) ; The Macro that creates the "object".
Structure NAME ; The structure of the "object". Contains pointers (prototyped) to the methods. A list of elements
SizeOf.i ; as well as the size of the user defined structure
*contains.Proto_Set_Contains
*add.Proto_Set_Add
*delete.Proto_Set_Delete
*FILTER.Proto_Set_FILTER
List elements.STRUCT()
EndStructure
Define NAME.NAME ; Create the actual new Object Variable
NAME\SizeOf = SizeOf(STRUCT) ; Save the size of the structure within the object variable, as it is needed for ComparyMemory() etc. later on.
; Definition of the methods our data type uses:
Procedure NAME#_FILTER(*IN.STRUCT, *NAME.NAME) ;FILTER() - RETURN FALSE to ABORT insertion
ForEach *NAME\elements()
If CompareMemory(*IN, *NAME\elements(), *NAME\SizeOf)
ProcedureReturn #False
EndIf
Next
ProcedureReturn #True
EndProcedure
Procedure NAME#_add(*var.STRUCT) ; add() - adds an element to the list. Uses the filter() function to check whether or not to add the element
Shared NAME
ForEach NAME\elements()
If NAME\FILTER(*var, NAME)=#False
ProcedureReturn #False
EndIf
Next
AddElement(NAME\elements())
CopyMemory(*var, @NAME\elements(), NAME\SizeOf)
ProcedureReturn #True
EndProcedure
Procedure NAME#_contains(*var.STRUCT) ; contains() - checks if an element is contained in the set.
Shared NAME
ResetList(NAME\elements())
While NextElement(NAME\elements())
If CompareMemory(*var, @NAME\elements(), NAME\SizeOf)
ProcedureReturn #True
EndIf
Wend
EndProcedure
Procedure NAME#_delete(*var.STRUCT) ; delete() - Delete an element from the set.
Shared NAME
ForEach NAME\elements()
If CompareMemory(*var, NAME\elements(), NAME\SizeOf)
DeleteElement(NAME\elements(), #True)
EndIf
Next
EndProcedure
NAME\contains = @NAME#_contains() ;Add Functions to Object Variable
NAME\add = @NAME#_add() ;Add Functions to Object Variable
NAME\delete = @NAME#_delete() ;Add Functions to Object Variable
NAME\FILTER = @NAME#_FILTER() ;Add Functions to Object Variable
EndMacro
DisableExplicit
;--- END INCLUDE